diff options
author | Aleksey Veresov <aleksey@veresov.pro> | 2019-11-13 19:16:21 +0300 |
---|---|---|
committer | Aleksey Veresov <aleksey@veresov.pro> | 2019-11-13 19:16:21 +0300 |
commit | 23f3f8592c21ee58b0ac040736b5b766d52de193 (patch) | |
tree | 43e41480fab64d68274340f8fd934bd20c5f27b2 /src | |
parent | b11b1c52280f172ebfa42c3da906ea9aa3ea8799 (diff) | |
download | magi-23f3f8592c21ee58b0ac040736b5b766d52de193.tar magi-23f3f8592c21ee58b0ac040736b5b766d52de193.tar.xz magi-23f3f8592c21ee58b0ac040736b5b766d52de193.zip |
Cosmetical changes.
Diffstat (limited to 'src')
-rw-r--r-- | src/cgi.c | 112 | ||||
-rw-r--r-- | src/cgi.h | 8 | ||||
-rw-r--r-- | src/cookie.c | 147 | ||||
-rw-r--r-- | src/cookie.h | 24 | ||||
-rw-r--r-- | src/fastcgi.h | 21 | ||||
-rw-r--r-- | src/field.c | 19 | ||||
-rw-r--r-- | src/field.h | 24 | ||||
-rw-r--r-- | src/log.c | 9 | ||||
-rw-r--r-- | src/log.h | 2 | ||||
-rw-r--r-- | src/multipart.c | 234 | ||||
-rw-r--r-- | src/multipart.h | 14 | ||||
-rw-r--r-- | src/param.c | 19 | ||||
-rw-r--r-- | src/param.h | 20 | ||||
-rw-r--r-- | src/request.c | 4 | ||||
-rw-r--r-- | src/request.h | 45 | ||||
-rw-r--r-- | src/urlencoded.c | 84 | ||||
-rw-r--r-- | src/urlencoded.h | 2 | ||||
-rw-r--r-- | src/utils.h | 62 |
18 files changed, 416 insertions, 434 deletions
@@ -12,18 +12,16 @@ #include <stdlib.h> #include <string.h> - -extern char **environ; - +extern char ** environ; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * CGI Request Handling */ /* Helpers for CGI Request Handling */ -static int plain_env(char **dest, char *env_name) +static int plain_env(char ** dest, char * env_name) { - int ok = 1; - const char *env = getenv(env_name); + int ok = 1; + const char * env = getenv(env_name); if (env) { *dest = str_alloc(strlen(env)); if (*dest) { @@ -37,24 +35,24 @@ static int plain_env(char **dest, char *env_name) return ok; } -static int lower_env(char **dest, char *env_name) +static int lower_env(char ** dest, char * env_name) { int ok = plain_env(dest, env_name); lowercase(*dest); return ok; } -static int cgi_http_env(struct magi_request *r) +static int cgi_http_env(struct magi_request * r) { - int ok = 1; - char **env = environ; + int ok = 1; + char ** env = environ; r->http_params = 0; while (*env) { if (!strncmp(*env, "HTTP_", 5) && strncmp(*env, "HTTP_COOKIE=", 12)) { struct magi_param param; /* At least one '=' must be in *env, according to format. */ - char *name_end = strchr(*env, '='); - param.name = str_alloc(name_end - *env - 5); + char * name_end = strchr(*env, '='); + param.name = str_alloc(name_end - *env - 5); if (param.name) { memcpy(param.name, *env + 5, name_end - *env - 5); param.data = str_alloc(strlen(name_end + 1)); @@ -75,31 +73,31 @@ static int cgi_http_env(struct magi_request *r) return ok; } -static int cgi_env(struct magi_request *r) +static int cgi_env(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"); + 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; } -static int cgi_cookies(struct magi_cookie_list **list) +static int cgi_cookies(struct magi_cookie_list ** list) { - int ok = 1; - const char *env = getenv("HTTP_COOKIE"); - *list = 0; + int ok = 1; + const char * env = getenv("HTTP_COOKIE"); + *list = 0; if (env && *env) { ok = magi_parse_cookie(list, env); } else { @@ -108,10 +106,10 @@ static int cgi_cookies(struct magi_cookie_list **list) return ok; } -static int cgi_input_get(char **input) +static int cgi_input_get(char ** input) { - int ok = 1; - const char *env_input = getenv("QUERY_STRING"); + int ok = 1; + const char * env_input = getenv("QUERY_STRING"); if (env_input) { *input = str_alloc(strlen(env_input)); if (*input) { @@ -123,7 +121,7 @@ static int cgi_input_get(char **input) return ok; } -static int cgi_input_post(char **input, int max) +static int cgi_input_post(char ** input, int max) { int ok = 1; int input_len = strtoul(getenv("CONTENT_LENGTH"), 0, 10); @@ -141,10 +139,10 @@ static int cgi_input_post(char **input, int max) return ok; } -static char *bound(const char *type) +static char * bound(const char * type) { - char *res = 0; - type = strchr(type, '='); + char * res = 0; + type = strchr(type, '='); if (type) { type += strspn(type, " \t") + 1; if (*type == '"') { @@ -157,44 +155,38 @@ static char *bound(const char *type) return res; } -static int intput_getter(void *any) +static int intput_getter(void * any) { return getchar(); } - /* 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 -) +int magi_cgi_request(struct magi_request * request, + 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; if (request->method) { if (!strcmp(request->method, "post")) { - const char *t = getenv("CONTENT_TYPE"); + const char * t = getenv("CONTENT_TYPE"); if (t) { if (!strncmp(t, "multipart/form-data", 19)) { - char *boundary = bound(t); + char * boundary = bound(t); if (boundary && *boundary) { - ok = magi_parse_multipart( - &request->fields, - intput_getter, - 0, - boundary, - callback - ); + ok = magi_parse_multipart(&request->fields, + intput_getter, 0, boundary, callback); } else { ok = 0; magi_log("[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); - ok = ok && magi_parse_urlencoded(&request->fields, in); + char * in = 0; + ok = cgi_input_post(&in, max_post); + if (ok) { + ok = magi_parse_urlencoded(&request->fields, in); + } free(in); } else { ok = 0; @@ -205,9 +197,9 @@ int magi_cgi_request( magi_log("[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); + char * in = 0; + ok = cgi_input_get(&in); + ok = ok && magi_parse_urlencoded(&request->fields, in); free(in); } } @@ -9,13 +9,11 @@ * Constructs request using environment variables and standart I/O; * Returns null if succeed, otherwise error code. */ -int magi_cgi_request( - struct magi_request *request, +int magi_cgi_request(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 -); + 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 4e757e6..8926d40 100644 --- a/src/cookie.c +++ b/src/cookie.c @@ -18,27 +18,21 @@ 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, dt_port }; struct automata { - struct magi_cookie_list **list; - struct magi_cookie cookie; - char *buf; - int buf_len; - int buf_size; - int is_first; - int is_cookie2; - int is_quoted; - enum data_type data_t; + struct magi_cookie_list ** list; + struct magi_cookie cookie; + char * buf; + int buf_len; + int buf_size; + int is_first; + int is_cookie2; + int is_quoted; + enum data_type data_t; }; -static void nulify_cookie(struct automata *a) +static void nulify_cookie(struct automata * a) { a->cookie.name = 0; a->cookie.data = 0; @@ -47,24 +41,24 @@ static void nulify_cookie(struct automata *a) a->cookie.port = 0; } -static void buf_new(struct automata *a) +static void buf_new(struct automata * a) { a->buf = 0; a->buf_len = 0; a->buf_size = 1; } -static int buf_add(struct automata *a, char c) +static int buf_add(struct automata * a, char c) { int ok = 1; if (a->buf_len == a->buf_size - 1) { a->buf_size *= 2; - a->buf = realloc(a->buf, a->buf_size); + a->buf = realloc(a->buf, a->buf_size); } if (a->buf) { a->buf_len++; a->buf[a->buf_len - 1] = c; - a->buf[a->buf_len] = 0; + a->buf[a->buf_len] = 0; } else { ok = 0; magi_log("[cookie] Cannot allocate automata buffer."); @@ -72,7 +66,7 @@ static int buf_add(struct automata *a, char c) return ok; } -static enum data_type what_is_name(const struct automata *a) +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")) { @@ -89,7 +83,7 @@ static enum data_type what_is_name(const struct automata *a) return data_t; } -static int end_name(struct automata *a) +static int end_name(struct automata * a) { int ok = 1; a->data_t = what_is_name(a); @@ -106,14 +100,22 @@ static int end_name(struct automata *a) return ok; } -static int end_data(struct automata *a) +static int end_data(struct automata * a) { int ok = 1; switch (a->data_t) { - case dt_plain: a->cookie.data = a->buf; break; - case dt_path: a->cookie.path = a->buf; break; - case dt_domain: a->cookie.domain = a->buf; break; - case dt_port: a->cookie.port = a->buf; break; + case dt_plain: + a->cookie.data = a->buf; + break; + case dt_path: + a->cookie.path = a->buf; + break; + case dt_domain: + a->cookie.domain = a->buf; + break; + case dt_port: + a->cookie.port = a->buf; + break; case dt_version: if (strcmp(a->buf, "1")) { ok = 0; @@ -124,7 +126,7 @@ static int end_data(struct automata *a) return ok; } -static enum st parse_pre_name(struct automata *a, char c) +static enum st parse_pre_name(struct automata * a, char c) { enum st state; if (c == ' ' || c == '\t') { @@ -141,7 +143,7 @@ static enum st parse_pre_name(struct automata *a, char c) return state; } -static enum st parse_name(struct automata *a, char c) +static enum st parse_name(struct automata * a, char c) { enum st state; if (c == '=') { @@ -166,7 +168,7 @@ static enum st parse_name(struct automata *a, char c) return state; } -static enum st parse_post_name(struct automata *a, char c) +static enum st parse_post_name(struct automata * a, char c) { enum st state; if (c == '=') { @@ -175,21 +177,20 @@ 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_log("[cookie] Waiting for name-value separator, " + "readed: \\%o (render: %c).", + c, c); } return state; } -static enum st parse_pre_data(struct automata *a, char c) +static enum st parse_pre_data(struct automata * a, char c) { enum st state; if (c == ' ' || c == '\t') { state = st_pre_data; } else if (c == '"') { - state = st_data; + state = st_data; a->is_quoted = 1; } else if (32 <= c && c <= 126 && !strchr("()<>@,;:\\\"/[]?={}", c)) { state = st_data; @@ -203,7 +204,7 @@ static enum st parse_pre_data(struct automata *a, char c) return state; } -static enum st parse_not_quoted_data(struct automata *a, char c) +static enum st parse_not_quoted_data(struct automata * a, char c) { enum st state; if (c == ';' || (c == ',' && a->is_first)) { @@ -218,21 +219,20 @@ static enum st parse_not_quoted_data(struct automata *a, char c) state = st_error; } } else if (32 <= c && c <= 126 && !strchr("()<>@,;:\\\"/[]?={}", c)) { - state = st_data; + state = st_data; if (!buf_add(a, c)) { state = st_error; } } else { state = st_error; - magi_log( - "[cookie] Reading not-quoted value, " - "readed: \\%o (render: %c).", c, c - ); + magi_log("[cookie] Reading not-quoted value, " + "readed: \\%o (render: %c).", + c, c); } return state; } -static enum st parse_data(struct automata *a, char c) +static enum st parse_data(struct automata * a, char c) { enum st state; if (a->is_quoted) { @@ -251,7 +251,7 @@ static enum st parse_data(struct automata *a, char c) return state; } -static enum st parse_post_data(struct automata *a, char c) +static enum st parse_post_data(struct automata * a, char c) { enum st state; if (c == ';' || (c == ',' && a->is_first)) { @@ -260,15 +260,14 @@ 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).", c, c - ); + magi_log("[cookie] Waiting for separator between name-value pairs, " + "readed: \\%o (render: %c).", + c, c); } return state; } -static int parse_end(struct automata *a, enum st s) +static int parse_end(struct automata * a, enum st s) { int ok = 0; if (s == st_post_data) { @@ -299,21 +298,33 @@ static int parse_end(struct automata *a, enum st s) return ok; } -int magi_parse_cookie(struct magi_cookie_list **list, const char *input) +int magi_parse_cookie(struct magi_cookie_list ** list, const char * input) { - struct automata a = { 0, { 0, 0, 0, 0, 0}, 0, 0, 1, 1, 0, 0, 0 }; + struct automata a = { 0, { 0, 0, 0, 0, 0 }, 0, 0, 1, 1, 0, 0, 0 }; enum st state = st_pre_name; - a.list = list; + a.list = list; while (*input && state) { char c = *input++; switch (state) { - case st_pre_name: state = parse_pre_name(&a, c); break; - case st_name: state = parse_name(&a, c); break; - case st_post_name: state = parse_post_name(&a, c); break; - case st_pre_data: state = parse_pre_data(&a, c); break; - case st_data: state = parse_data(&a, c); break; - case st_post_data: state = parse_post_data(&a, c); - default: break; + case st_pre_name: + state = parse_pre_name(&a, c); + break; + case st_name: + state = parse_name(&a, c); + break; + case st_post_name: + state = parse_post_name(&a, c); + break; + case st_pre_data: + state = parse_pre_data(&a, c); + break; + case st_data: + state = parse_data(&a, c); + break; + case st_post_data: + state = parse_post_data(&a, c); + default: + break; } } return parse_end(&a, state); @@ -324,13 +335,11 @@ 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 -) + struct magi_cookie_list ** list, struct magi_cookie * item) { - struct magi_cookie_list *old = *list; - int ok = 1; - *list = malloc(sizeof(**list)); + struct magi_cookie_list * old = *list; + int ok = 1; + *list = malloc(sizeof(**list)); if (*list) { (*list)->next = old; (*list)->item = *item; @@ -342,9 +351,9 @@ int magi_cookie_list_add( return ok; } -char *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) { - char *data = 0; + char * data = 0; if (list && name) { if (!strcmp(list->item.name, name)) { data = list->item.data; @@ -355,7 +364,7 @@ char *magi_cookie_list_get(struct magi_cookie_list *list, const char *name) return data; } -void magi_cookie_list_destroy(struct magi_cookie_list *list) +void magi_cookie_list_destroy(struct magi_cookie_list * list) { if (list) { magi_cookie_list_destroy(list->next); diff --git a/src/cookie.h b/src/cookie.h index b0a7fb0..f72736b 100644 --- a/src/cookie.h +++ b/src/cookie.h @@ -6,42 +6,40 @@ * Cookie */ struct magi_cookie { - char *name; /* name: free(name) is valid. */ - char *data; /* data: free(data) is valid. */ + char * name; /* name: free(name) is valid. */ + char * data; /* data: free(data) is valid. */ /* Following is used in Cookie2: */ - char *path; /* path: free(path) is valid. */ - char *domain; /* domain: free(domain) is valid. */ - char *port; /* port: free(port) is valid. */ + char * path; /* path: free(path) is valid. */ + char * domain; /* domain: free(domain) is valid. */ + char * port; /* port: free(port) is valid. */ }; /* Null is valid "struct magi_cookie_list *" object. */ struct magi_cookie_list { - struct magi_cookie_list *next; - struct magi_cookie item; + struct magi_cookie_list * next; + struct magi_cookie item; }; /* Returns null in case of error. */ -int magi_parse_cookie(struct magi_cookie_list **list, const char *input); +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 -); + struct magi_cookie_list ** list, struct magi_cookie * item); /* * Searchs for first node in list: node.name == name, name is C-string; * Returns node.data if succeed, otherwise result is null. */ -char *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); /* * Destroys list; list is not valid after destruction. */ -void magi_cookie_list_destroy(struct magi_cookie_list *list); +void magi_cookie_list_destroy(struct magi_cookie_list * list); #endif diff --git a/src/fastcgi.h b/src/fastcgi.h index e69de29..9213c3c 100644 --- a/src/fastcgi.h +++ b/src/fastcgi.h @@ -0,0 +1,21 @@ +#ifndef MAGI_INCLUDED_FASTCGI +#define MAGI_INCLUDED_FASTCGI + +#include "field.h" +#include "request.h" + + +struct magi_session { + void (*callback)(struct magi_field * field, char * buffer, int len); + int max_post; + struct magi_socket_list * sockets; +}; + +/* + * Returns null if succeed, otherwise error code. + */ +int magi_fast_cgi_request( + struct magi_request * request, struct magi_session * session); + + +#endif diff --git a/src/field.c b/src/field.c index 0fa2664..7b0b919 100644 --- a/src/field.c +++ b/src/field.c @@ -9,11 +9,12 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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; - *list = malloc(sizeof(**list)); + struct magi_field_list * old = *list; + int ok = 1; + *list = malloc(sizeof(**list)); if (*list) { (*list)->next = old; (*list)->item = *item; @@ -25,12 +26,10 @@ int magi_field_list_add(struct magi_field_list **list, struct magi_field *item) 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; + struct magi_field * item = 0; if (list && name) { if (!strcmp(list->item.name, name)) { item = &list->item; @@ -41,7 +40,7 @@ struct magi_field *magi_field_list_get( return item; } -void magi_field_list_destroy(struct magi_field_list *list) +void magi_field_list_destroy(struct magi_field_list * list) { if (list) { magi_field_list_destroy(list->next); diff --git a/src/field.h b/src/field.h index a6fcff3..8387863 100644 --- a/src/field.h +++ b/src/field.h @@ -6,16 +6,16 @@ * Form Field */ struct magi_field { - char *name; /* name: free(name) is valid. */ - char *data; /* data: free(data) is valid. */ - int len; /* Length of data. */ - struct magi_param_list *params; /* Only used if field is for file. */ + char * name; /* name: free(name) is valid. */ + char * data; /* data: free(data) is valid. */ + int len; /* Length of data. */ + struct magi_param_list * params; /* Only used if field is for file. */ }; /* Null is valid "struct magi_field_list *" object. */ struct magi_field_list { - struct magi_field_list *next; - struct magi_field item; + struct magi_field_list * next; + struct magi_field item; }; /* @@ -23,23 +23,19 @@ struct magi_field_list { * Returns null in case of error. */ int magi_field_list_add( - struct magi_field_list **list, - struct magi_field *item -); + 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. */ -void magi_field_list_destroy(struct magi_field_list *list); +void magi_field_list_destroy(struct magi_field_list * list); #endif @@ -1,16 +1,17 @@ #include "log.h" -#include <stdio.h> #include <stdarg.h> +#include <stdio.h> + -void magi_log(const char *format, ...) +void magi_log(const char * format, ...) { - #ifdef ERRLOG +#ifdef ERRLOG va_list args; va_start(args, format); fputs("MAGI ERROR: ", stderr); vfprintf(stderr, format, args); fputc('\n', stderr); va_end(args); - #endif +#endif } @@ -2,7 +2,7 @@ #define MAGI_INCLUDED_LOG -void magi_log(const char *format, ...); +void magi_log(const char * format, ...); #endif diff --git a/src/multipart.c b/src/multipart.c index 94a37cb..c49be9b 100644 --- a/src/multipart.c +++ b/src/multipart.c @@ -4,72 +4,12 @@ #include "log.h" #include "param.h" #include <ctype.h> -#include <stdlib.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Local Shortcuts - */ -static int add(char **dest, int *len, int *size, char c) -{ - int ok = 1; - if (*len + 1 == *size) { - *size *= 2; - *dest = realloc(*dest, *size); - } - if (*dest == 0) { - ok = 0; - magi_log("[multipart] Cannot allocate string."); - } else { - (*dest)[*len] = c; - ++*len; - (*dest)[*len] = 0; - } - return ok; -} - -static void lowercase(char *str) -{ - if (str) { - while (*str) { - *str = tolower(*str); - ++str; - } - } -} - -static char *create_str(char *begin, char *end) -{ - char *res; - res = malloc(end - begin + 1); - if (res) { - memcpy(res, begin, end - begin); - res[end - begin] = 0; - } else { - magi_log("[multipart] Cannot allocate string."); - } - return res; -} - -static int is_token(char c) -{ - return 32 <= c && c <= 126 && !strchr("()<>@,;:\\\"/[]?={} \t", c); -} - -static int is_str_token(char *str) -{ - int is = str && *str; /* Empty string is not valid. */ - while (is && *str) { - is = is_token(*str); - ++str; - } - return is; -} - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Automata for multipart/form-data */ enum st { @@ -84,30 +24,30 @@ enum st { }; struct automata { - struct magi_field_list **list; - struct magi_field field; - struct magi_param param; - char *buf; - int buf_size; - int size; - int len; - char *boundary; - int boundary_pos; - int boundary_len; - int is_end_suspected; - int is_CR_readed; - int is_quoted; - void (*callback)(struct magi_field *field, char *buffer, int size); + struct magi_field_list ** list; + struct magi_field field; + struct magi_param param; + char * buf; + int buf_size; + int size; + int len; + char * boundary; + int boundary_pos; + int boundary_len; + int is_end_suspected; + int is_CR_readed; + int is_quoted; + void (*callback)(struct magi_field * field, char * buffer, int size); }; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Automata Shortcuts */ -static int content_disposition(struct automata *a) +static int content_disposition(struct automata * a) { - int ok = 1; - char *name = strchr(a->param.data, '='); + int ok = 1; + char * name = strchr(a->param.data, '='); if (name) { name += strspn(name, " \t") + 1; if (*name == '"') { @@ -125,10 +65,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.", a->field.name - ); + magi_log("[multipart] Content-disposition value is not valid, " + "readed: %s.", + a->field.name); } } if (ok) { @@ -144,14 +83,14 @@ static int content_disposition(struct automata *a) return ok; } -static int param_end(struct automata *a) +static int param_end(struct automata * a) { int ok = 1; lowercase(a->param.name); if (!strcmp(a->param.name, "content-disposition")) { ok = content_disposition(a); } else { - ok = magi_param_list_add(&a->field.params, &a->param); + ok = magi_param_list_add(&a->field.params, &a->param); a->param.name = 0; a->param.data = 0; } @@ -160,7 +99,7 @@ static int param_end(struct automata *a) return ok; } -static int field_end(struct automata *a) +static int field_end(struct automata * a) { int ok; if (a->field.name == 0) { @@ -172,7 +111,7 @@ static int field_end(struct automata *a) a->buf_size = 0; } a->field.len = a->len; - ok = magi_field_list_add(a->list, &a->field); + ok = magi_field_list_add(a->list, &a->field); if (!ok) { free(a->field.name); free(a->field.data); @@ -192,9 +131,9 @@ static int field_end(struct automata *a) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Boundary interfaces */ -static char sepget(const struct automata *a) +static char sepget(const struct automata * a) { - char c; + char c; const int pos_after = a->boundary_pos - 4 - a->boundary_len; if (a->boundary_pos == 0) { c = '\r'; @@ -214,14 +153,14 @@ static char sepget(const struct automata *a) return c; } -static int seplen(const struct automata *a) +static int seplen(const struct automata * a) { return a->boundary_len + 6; } -static char endget(const struct automata *a) +static char endget(const struct automata * a) { - char c; + char c; const int pos_after = a->boundary_pos - 4 - a->boundary_len; if (a->boundary_pos == 0) { c = '\r'; @@ -243,13 +182,13 @@ static char endget(const struct automata *a) return c; } -static int endlen(const struct automata *a) +static int endlen(const struct automata * a) { return a->boundary_len + 8; } -static int is_semiend(const struct automata *a) -{ /* Is end readed, expect last two chars, which are CR LF? */ +static int is_semiend(const struct automata * a) +{ /* Is end readed, expect last two chars, which are CR LF? */ return a->is_end_suspected && (a->boundary_pos == endlen(a) - 2); } @@ -257,7 +196,7 @@ static int is_semiend(const struct automata *a) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * State analysers */ -static enum st parse_begin(struct automata *a, char c) +static enum st parse_begin(struct automata * a, char c) { enum st state; if (sepget(a) == c) { @@ -268,26 +207,26 @@ static enum st parse_begin(struct automata *a, char c) state = st_begin; } } else { - state = st_begin; + state = st_begin; a->boundary_pos = 0; } return state; } -static enum st parse_pname_pre(struct automata *a, char c) +static enum st parse_pname_pre(struct automata * a, char c) { enum st state; if (a->is_CR_readed) { a->is_CR_readed = 0; if (c == '\n') { - state = st_data; + state = st_data; a->boundary_pos = 0; } else { state = st_error; magi_log("[multipart] Waiting for name, CR is readed alone."); } } else if (c == '\r') { - state = st_pname_pre; + state = st_pname_pre; a->is_CR_readed = 1; } else if (is_token(c)) { if (add(&a->param.name, &a->len, &a->size, c)) { @@ -298,13 +237,12 @@ static enum st parse_pname_pre(struct automata *a, char c) } else { state = st_error; magi_log( - "[multipart] Waiting for name, readed: \\%o (render: %c).", c, c - ); + "[multipart] Waiting for name, readed: \\%o (render: %c).", c, c); } return state; } -static enum st parse_pname(struct automata *a, char c) +static enum st parse_pname(struct automata * a, char c) { enum st state; if (c == ':') { @@ -321,14 +259,12 @@ 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_log("[multipart] Reading name, readed: \\%o (render: %c).", c, c); } return state; } -static enum st parse_pname_end(struct automata *a, char c) +static enum st parse_pname_end(struct automata * a, char c) { enum st state; if (c == ':') { @@ -339,15 +275,14 @@ 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_log("[multipart] Waiting for name-value separator, " + "readed: \\%o (render: %c).", + c, c); } return state; } -static enum st parse_pdata(struct automata *a, char c) +static enum st parse_pdata(struct automata * a, char c) { enum st state; if (a->is_CR_readed) { @@ -380,7 +315,7 @@ static enum st parse_pdata(struct automata *a, char c) return state; } -static void apply_callback(struct automata *a) +static void apply_callback(struct automata * a) { if (a->callback && a->buf_size == magi_parse_multipart_callback_size) { a->callback(&a->field, a->buf, a->buf_size); @@ -388,13 +323,13 @@ static void apply_callback(struct automata *a) } } -static enum st data_add(struct automata *a, char c) +static enum st data_add(struct automata * a, char c) { static int max_buf_size = magi_parse_multipart_callback_size + 1; enum st state; - char **dest; - int *len; - int *size; + char ** dest; + int * len; + int * size; int pos = a->boundary_pos; state = st_data; a->boundary_pos = 0; @@ -433,7 +368,7 @@ static enum st data_add(struct automata *a, char c) return state; } -static enum st parse_data(struct automata *a, char c) +static enum st parse_data(struct automata * a, char c) { enum st state; if (a->is_end_suspected) { @@ -466,7 +401,7 @@ static enum st parse_data(struct automata *a, char c) return state; } -static enum st parse_end(struct automata *a, char c) +static enum st parse_end(struct automata * a, char c) { return st_end; } @@ -475,22 +410,36 @@ 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; - int c; + int c; for (c = next(thing); state && c != EOF; c = next(thing)) { switch (state) { - case st_begin: state = parse_begin(a, c); break; - case st_pname_pre: state = parse_pname_pre(a, c); break; - case st_pname: state = parse_pname(a, c); break; - case st_pname_end: state = parse_pname_end(a, c); break; - case st_pdata: state = parse_pdata(a, c); break; - case st_data: state = parse_data(a, c); break; - case st_end: state = parse_end(a, c); - default: break; + case st_begin: + state = parse_begin(a, c); + break; + case st_pname_pre: + state = parse_pname_pre(a, c); + break; + case st_pname: + state = parse_pname(a, c); + break; + case st_pname_end: + state = parse_pname_end(a, c); + break; + case st_pdata: + state = parse_pdata(a, c); + break; + case st_data: + state = parse_data(a, c); + break; + case st_end: + state = parse_end(a, c); + default: + break; } } if (state == st_data && is_semiend(a)) { @@ -512,23 +461,18 @@ run_automata(struct automata *a, int (*next)(void *thing), void *thing) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 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)) { - struct automata a = { - 0, { 0, 0, 0 }, { 0, 0 }, 0, 0, 1, 0, 0, 2, 0, 0, 0 - }; - int ok = 0; - a.list = list; - a.boundary = boundary; - a.boundary_len = strlen(boundary); - a.callback = callback; - a.buf = malloc(magi_parse_multipart_callback_size + 1); + struct automata a + = { 0, { 0, 0, 0 }, { 0, 0 }, 0, 0, 1, 0, 0, 2, 0, 0, 0 }; + int ok = 0; + a.list = list; + a.boundary = boundary; + a.boundary_len = strlen(boundary); + a.callback = callback; + a.buf = malloc(magi_parse_multipart_callback_size + 1); if (a.buf) { ok = run_automata(&a, get_next, get_next_arg); free(a.buf); diff --git a/src/multipart.h b/src/multipart.h index a7437eb..e9a0004 100644 --- a/src/multipart.h +++ b/src/multipart.h @@ -4,20 +4,14 @@ #include "field.h" -enum { - magi_parse_multipart_callback_size = 64 -}; +enum { magi_parse_multipart_callback_size = 64 }; -int magi_parse_multipart( - struct magi_field_list **list, - int (*get_next)(void *), - void *get_next_arg, - char *boundary, +int magi_parse_multipart(struct magi_field_list ** list, + int (*get_next)(void *), void * get_next_arg, char * boundary, /* End if size < magi_parse_multipart_callback_size. */ /* Null callback means filling list. */ - void (*callback)(struct magi_field *field, char *buffer, int size) -); + void (*callback)(struct magi_field * field, char * buffer, int size)); #endif diff --git a/src/param.c b/src/param.c index ebd2216..8921019 100644 --- a/src/param.c +++ b/src/param.c @@ -8,11 +8,12 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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; - *list = malloc(sizeof(**list)); + struct magi_param_list * old = *list; + int ok = 1; + *list = malloc(sizeof(**list)); if (*list) { (*list)->next = old; (*list)->item = *item; @@ -24,12 +25,10 @@ int magi_param_list_add(struct magi_param_list **list, struct magi_param *item) 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; + struct magi_param * item = 0; if (list && name) { if (!strcmp(list->item.name, name)) { item = &list->item; @@ -40,7 +39,7 @@ struct magi_param *magi_param_list_get( return item; } -void magi_param_list_destroy(struct magi_param_list *list) +void magi_param_list_destroy(struct magi_param_list * list) { if (list) { magi_param_list_destroy(list->next); diff --git a/src/param.h b/src/param.h index a9a5942..ede1586 100644 --- a/src/param.h +++ b/src/param.h @@ -6,14 +6,14 @@ * Parameter */ struct magi_param { - char *name; /* name: free(name) is valid. */ - char *data; /* data: free(data) is valid. */ + char * name; /* name: free(name) is valid. */ + char * data; /* data: free(data) is valid. */ }; /* Null is valid "struct magi_param_list *" object. */ struct magi_param_list { - struct magi_param_list *next; - struct magi_param item; + struct magi_param_list * next; + struct magi_param item; }; /* @@ -21,23 +21,19 @@ struct magi_param_list { * Returns null in case of error. */ int magi_param_list_add( - struct magi_param_list **list, - struct magi_param *item -); + 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. */ -void magi_param_list_destroy(struct magi_param_list *list); +void magi_param_list_destroy(struct magi_param_list * list); #endif diff --git a/src/request.c b/src/request.c index 58eefc6..73c4730 100644 --- a/src/request.c +++ b/src/request.c @@ -1,7 +1,7 @@ #include "request.h" -#include "field.h" #include "cookie.h" +#include "field.h" #include "param.h" #include <stdlib.h> @@ -9,7 +9,7 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Common Request Handling */ -void magi_request_destroy(struct magi_request *request) +void magi_request_destroy(struct magi_request * request) { if (request) { magi_field_list_destroy(request->fields); diff --git a/src/request.h b/src/request.h index 6b9df6e..bd9c521 100644 --- a/src/request.h +++ b/src/request.h @@ -8,9 +8,11 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Request - * - * Example for enivronmental variables: - * Request: http://example.com/cgi-bin/script/foo/bar?var2=url%20enc + * + * Can be generated via CGI handler (magi_cgi_request) or + * as session in Fast CGI (magi_fast_cgi_request). + * + * Example: http://example.com/cgi-bin/script/foo/bar?var2=url%20enc * method: get * uri: /cgi-bin/script/foo/bar?var2=url%20enc * document_root: { absolute path to root directory of domain } @@ -28,30 +30,31 @@ * path_info: /foo/bar */ struct magi_request { - struct magi_field_list *fields; - struct magi_cookie_list *cookies; - char *method; - char *uri; - char *document_root; - char *document_uri; - char *script_name; - char *script_filename; - char *remote_addr; - char *remote_port; - char *server_addr; - char *server_name; - char *server_port; - char *server_protocol; - char *server_software; - char *path_info; - struct magi_param_list *http_params; + struct magi_field_list * fields; + struct magi_cookie_list * cookies; + char * method; + char * uri; + char * document_root; + char * document_uri; + char * script_name; + char * script_filename; + char * remote_addr; + char * remote_port; + char * server_addr; + char * server_name; + char * server_port; + char * server_protocol; + char * server_software; + char * path_info; + struct magi_param_list * http_params; + /* TODO: error. */ }; /* * Destroys request; request is not valid after destruction. */ -void magi_request_destroy(struct magi_request *request); +void magi_request_destroy(struct magi_request * request); #endif diff --git a/src/urlencoded.c b/src/urlencoded.c index c208180..1edcf99 100644 --- a/src/urlencoded.c +++ b/src/urlencoded.c @@ -8,50 +8,28 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Shortcuts - */ -/* Shouldn't be called with 'c' as not hex digit. */ -static char from_hex(char c) -{ - char num; - if (isdigit(c)) { - num = c - '0'; - } else { - num = toupper(c) - 'A' + 10; - } - return num; -} - -static int is_hex(char c) -{ - return isdigit(c) || strchr("ABCDEF", toupper(c)); -} - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * URL Decoding */ -static int deurl(char **data) +static int deurl(char ** data) { int ok = 1; if (*data) { - char *val = *data; - int ti = 0; - int ci; + char * val = *data; + int ti = 0; + int ci; for (ci = 0; ok && val[ci]; ++ti, ++ci) { if (val[ci] == '%') { if (is_hex(val[ci + 1]) && is_hex(val[ci + 2])) { /* Since chars can be signed, arithmetics are not safe. */ - val[ti] = from_hex(val[ci + 2]); /* 00xx */ - val[ti] |= from_hex(val[ci + 1]) << 4; /* XXxx */ - ci += 2; + val[ti] = from_hex(val[ci + 2]); /* 00xx */ + val[ti] |= from_hex(val[ci + 1]) << 4; /* XXxx */ + ci += 2; } else { ok = 0; magi_log( "[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] - ); + val[ci + 1], val[ci + 2], val[ci + 1], val[ci + 2]); } } else if (val[ci] == '+') { val[ti] = ' '; @@ -71,21 +49,17 @@ static int deurl(char **data) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Urlencoded Automata */ -enum st { - st_error = 0, - st_name, - st_data -}; +enum st { st_error = 0, st_name, st_data }; struct automata { - struct magi_field_list **list; - struct magi_field field; - int size; - int len; + struct magi_field_list ** list; + struct magi_field field; + int size; + int len; }; -static enum st parse_name(struct automata *a, char c) +static enum st parse_name(struct automata * a, char c) { enum st state; if (c != '&' && c != ';') { @@ -95,7 +69,7 @@ static enum st parse_name(struct automata *a, char c) a->len = 0; } else { if (a->len == a->size - 1) { - a->size *= 2; + a->size *= 2; a->field.name = realloc(a->field.name, a->size); } if (!a->field.name) { @@ -110,12 +84,13 @@ 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_log( + "[urlencoded] Reading name, readed: \\%o (render: %c).", c, c); } return state; } -static enum st end_data(struct automata *a) +static enum st end_data(struct automata * a) { enum st state = st_error; if (deurl(&a->field.name) && deurl(&a->field.data)) { @@ -131,7 +106,7 @@ static enum st end_data(struct automata *a) return state; } -static enum st parse_data(struct automata *a, char c) +static enum st parse_data(struct automata * a, char c) { enum st state; if (c != '=') { @@ -139,7 +114,7 @@ static enum st parse_data(struct automata *a, char c) state = end_data(a); } else { if (a->len == a->size - 1) { - a->size *= 2; + a->size *= 2; a->field.data = realloc(a->field.data, a->size); } if (!a->field.data) { @@ -154,22 +129,27 @@ 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_log( + "[urlencoded] Reading data, readed: \\%o (render: %c).", c, c); } return state; } -int magi_parse_urlencoded(struct magi_field_list **list, const char *input) +int magi_parse_urlencoded(struct magi_field_list ** list, const char * input) { - enum st state = st_name; - struct automata a = { 0, { 0, 0, 0 }, 1, 0 }; + enum st state = st_name; + struct automata a = { 0, { 0, 0, 0 }, 1, 0 }; if (input && *input) { a.list = list; while (state && *input) { switch (state) { - case st_name: state = parse_name(&a, *input); break; - case st_data: state = parse_data(&a, *input); - default: break; + case st_name: + state = parse_name(&a, *input); + break; + case st_data: + state = parse_data(&a, *input); + default: + break; } ++input; } diff --git a/src/urlencoded.h b/src/urlencoded.h index 5902a24..838ae57 100644 --- a/src/urlencoded.h +++ b/src/urlencoded.h @@ -4,7 +4,7 @@ #include "field.h" -int magi_parse_urlencoded(struct magi_field_list **list, const char *input); +int magi_parse_urlencoded(struct magi_field_list ** list, const char * input); #endif diff --git a/src/utils.h b/src/utils.h index a6c0aff..f16ea3f 100644 --- a/src/utils.h +++ b/src/utils.h @@ -2,7 +2,7 @@ #define MAGI_INCLUDED_UTILS -static void lowercase(char *str) +static void lowercase(char * str) { if (str) { while (*str) { @@ -12,20 +12,22 @@ static void lowercase(char *str) } } -static char *create_str(const char *begin, const char *end) +static char * create_str(const char * begin, const char * end) { - char *res; + char * res; res = malloc(end - begin + 1); if (res) { memcpy(res, begin, end - begin); res[end - begin] = 0; + } else { + magi_log("Cannot allocate string."); } return res; } -static char *str_alloc(int len) +static char * str_alloc(int len) { - char *str = malloc(len + 1); + char * str = malloc(len + 1); if (str) { str[len] = 0; } else { @@ -34,5 +36,55 @@ static char *str_alloc(int len) return str; } +/* Shouldn't be called with 'c' as not hex digit. */ +static char from_hex(char c) +{ + char num; + if (isdigit(c)) { + num = c - '0'; + } else { + num = toupper(c) - 'A' + 10; + } + return num; +} + +static int is_hex(char c) +{ + return isdigit(c) || strchr("ABCDEF", toupper(c)); +} + +static int add(char ** dest, int * len, int * size, char c) +{ + int ok = 1; + if (*len + 1 == *size) { + *size *= 2; + *dest = realloc(*dest, *size); + } + if (*dest == 0) { + ok = 0; + magi_log("Cannot allocate string."); + } else { + (*dest)[*len] = c; + ++*len; + (*dest)[*len] = 0; + } + return ok; +} + +static int is_token(char c) +{ + return 32 <= c && c <= 126 && !strchr("()<>@,;:\\\"/[]?={} \t", c); +} + +static int is_str_token(char * str) +{ + int is = str && *str; /* Empty string is not valid. */ + while (is && *str) { + is = is_token(*str); + ++str; + } + return is; +} + #endif |