aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAleksey Veresov <aleksey@veresov.pro>2020-02-04 18:14:54 +0300
committerAleksey Veresov <aleksey@veresov.pro>2020-02-04 18:14:54 +0300
commit8ef310a22a54dca7a80947f83f03bc296ab298dd (patch)
tree739df8f259747508176ecfcdb32f06d711d6c244 /src
parent676f6520bf76867135f1af4fab5d69b3b212d198 (diff)
downloadmagi-8ef310a22a54dca7a80947f83f03bc296ab298dd.tar
magi-8ef310a22a54dca7a80947f83f03bc296ab298dd.tar.xz
magi-8ef310a22a54dca7a80947f83f03bc296ab298dd.zip
[magi]
Diffstat (limited to 'src')
-rw-r--r--src/cgi.c38
-rw-r--r--src/cgi.h15
-rw-r--r--src/cookie.h34
-rw-r--r--src/cookies.h10
-rw-r--r--src/error.h6
-rw-r--r--src/file.h25
-rw-r--r--src/inner_cookies.c (renamed from src/cookies.c)2
-rw-r--r--src/inner_cookies.h10
-rw-r--r--src/inner_multipart.c (renamed from src/multipart.c)2
-rw-r--r--src/inner_multipart.h13
-rw-r--r--src/inner_urlencoded.c144
-rw-r--r--src/inner_urlencoded.h13
-rw-r--r--src/magi.h16
-rw-r--r--src/multipart.h13
-rw-r--r--src/param.h24
-rw-r--r--src/request.h102
-rw-r--r--src/response.c64
-rw-r--r--src/response.h47
-rw-r--r--src/urlenc.c135
-rw-r--r--src/urlenc.h13
20 files changed, 391 insertions, 335 deletions
diff --git a/src/cgi.c b/src/cgi.c
index 7563613..a0661dc 100644
--- a/src/cgi.c
+++ b/src/cgi.c
@@ -1,14 +1,14 @@
#include "cgi.h"
#include "cookie.h"
-#include "cookies.h"
#include "error.h"
#include "file.h"
-#include "multipart.h"
+#include "inner_cookies.h"
+#include "inner_multipart.h"
+#include "inner_tools.h"
+#include "inner_urlencoded.h"
#include "param.h"
#include "request.h"
-#include "urlenc.h"
-#include "utils.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
@@ -132,7 +132,7 @@ static void cgi_url(struct magi_request * request)
char * in = 0;
cgi_input_get(&request->error, &in, request->url_params_max);
if (!request->error) {
- magi_urlenc(&request->url_params, request, in);
+ magi_urlencoded(&request->url_params, request, in);
}
free(in);
}
@@ -218,7 +218,7 @@ int magi_request_resume_cgi(struct magi_request * request)
char * in = 0;
cgi_input_post(e, &in, request->params_max);
if (!*e) {
- magi_urlenc(&request->params, request, in);
+ magi_urlencoded(&request->params, request, in);
}
free(in);
} else {
@@ -229,6 +229,11 @@ int magi_request_resume_cgi(struct magi_request * request)
return !request->error;
}
+int magi_request_full_cgi(magi_request *request)
+{
+ return magi_request_cgi(request) && magi_request_resume_cgi(request);
+}
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* CGI Response
@@ -268,6 +273,7 @@ void output_cookies(struct magi_cookie_list * list)
}
}
+
int magi_response_cgi(struct magi_response * response)
{
output_http_params(response->http_params);
@@ -278,14 +284,20 @@ int magi_response_cgi(struct magi_response * response)
return 1;
}
+int magi_response_cgi_clear(magi_response *response)
+{
+ int ok = magi_response_cgi(response);
+ magi_response_destroy(response);
+ return ok;
+}
+
+
int magi_error_cgi(enum magi_error error)
{
struct magi_response res;
magi_response_setup(&res);
magi_response_http(&res, "Status", "400 Bad Request");
- magi_response_content_type(&res, magi_xhtml);
- magi_response_add_format(
- &res,
+ magi_response_add_format(&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'>"
@@ -296,11 +308,5 @@ int magi_error_cgi(enum magi_error error)
"</body>"
"</html>",
magi_error_message(error));
- if (magi_response_cgi(&res)) {
- magi_response_destroy(&res);
- return 1;
- } else {
- magi_response_destroy(&res);
- return 0;
- }
+ return magi_response_cgi_clear(&res);
}
diff --git a/src/cgi.h b/src/cgi.h
index 6101de6..7e47ad0 100644
--- a/src/cgi.h
+++ b/src/cgi.h
@@ -8,20 +8,27 @@
/* Constructs non-post part of request from environment;
* Returns null only in case of error. */
-int magi_request_cgi(struct magi_request * request);
+int magi_request_cgi(magi_request *request);
/* Complete request with post data from standard input;
* Returns null only in case of error. */
-int magi_request_resume_cgi(struct magi_request * request);
+int magi_request_resume_cgi(magi_request *request);
+
+/* Shortcut for applying both previous. */
+int magi_request_full_cgi(magi_request *request);
/* Sends response to standard output;
* Returns null only in case of error. */
-int magi_response_cgi(struct magi_response * response);
+int magi_response_cgi(magi_response *response);
+
+/* Shortcut for magi_response_cgi with desctruction after it. */
+int magi_response_cgi_clear(magi_response *response);
+
/* Sends a standart response of Bad Request error to standard output;
* Returns null only in case of error. */
-int magi_error_cgi(enum magi_error error);
+int magi_error_cgi(magi_error error);
#endif
diff --git a/src/cookie.h b/src/cookie.h
index 82c914e..7eb3e9d 100644
--- a/src/cookie.h
+++ b/src/cookie.h
@@ -2,31 +2,31 @@
#define MAGI_INCLUDED_COOKIE
-struct magi_cookie {
+typedef struct magi_cookie {
/* All pointers must be valid as 'free' arguments. */
- char * name;
- char * data;
- char * path;
- char * domain;
- char * port;
-};
+ char *name;
+ char *data;
+ char *path; /* Without '/' at the end. */
+ char *domain; /* With dot at the begining. */
+ char *max_age; /* In seconds until discard, used only in response. */
+} magi_cookie;
-struct magi_cookie_list {
- struct magi_cookie_list * next; /* Must be valid as 'free' arguments. */
- struct magi_cookie item;
-};
+typedef struct magi_cookie_list {
+ struct magi_cookie_list *next; /* Must be valid as 'free' arguments. */
+ magi_cookie item;
+} magi_cookie_list;
/* Addition of item to top of list. Null <=> error. */
-int magi_cookie_list_add(struct magi_cookie_list ** list,
- struct magi_cookie * item);
+int magi_cookie_list_add(magi_cookie_list **list, 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);
+/* 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(magi_cookie_list *list, const char *name);
/* Freeing and invalidation of list. */
-void magi_cookie_list_destroy(struct magi_cookie_list * list);
+void magi_cookie_list_destroy(magi_cookie_list *list);
#endif
diff --git a/src/cookies.h b/src/cookies.h
deleted file mode 100644
index 98b2ada..0000000
--- a/src/cookies.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef MAGI_INCLUDED_COOKIES
-#define MAGI_INCLUDED_COOKIES
-
-#include "request.h"
-
-
-void magi_cookies(struct magi_request * request, const char * data);
-
-
-#endif
diff --git a/src/error.h b/src/error.h
index f8f0aed..4a91962 100644
--- a/src/error.h
+++ b/src/error.h
@@ -2,7 +2,7 @@
#define MAGI_INCLUDED_ERROR
-enum magi_error {
+typedef enum magi_error {
magi_error_none = 0,
magi_error_nobound,
magi_error_unknown,
@@ -13,9 +13,9 @@ enum magi_error {
magi_error_urlenc,
magi_error_multipart,
magi_error_limit
-};
+} magi_error;
-const char * magi_error_message(enum magi_error error);
+const char *magi_error_message(magi_error error);
#endif
diff --git a/src/file.h b/src/file.h
index 887bd31..4705031 100644
--- a/src/file.h
+++ b/src/file.h
@@ -4,28 +4,27 @@
#include "param.h"
-struct magi_file {
+typedef struct magi_file {
/* All pointers must be valid as 'free' arguments. */
- char * param_name; /* Name of corresponding form field */
- char * file_name; /* File name on user's computer */
- struct magi_param_list * params; /* Multipart params (e.g. type) */
-};
+ char *param_name; /* Name of corresponding form field */
+ char *file_name; /* File name on user's computer */
+ magi_param_list *params; /* Multipart params (e.g. type) */
+} magi_file;
-struct magi_file_list {
- struct magi_file_list * next; /* Must be valid as 'free' argument. */
- struct magi_file item;
-};
+typedef struct magi_file_list {
+ struct magi_file_list *next; /* Must be valid as 'free' argument. */
+ magi_file item;
+} magi_file_list;
/* Addition of item to top of list. Null <=> error. */
-int magi_file_list_add(struct magi_file_list ** list, struct magi_file * item);
+int magi_file_list_add(magi_file_list **list, magi_file *item);
/* First node in list: node.param_name == name; else null. */
-struct magi_file * magi_file_list_get(struct magi_file_list * list,
- const char * name);
+magi_file *magi_file_list_get(magi_file_list *list, const char *name);
/* Freeing and invalidation of list. */
-void magi_file_list_destroy(struct magi_file_list * list);
+void magi_file_list_destroy(magi_file_list *list);
#endif
diff --git a/src/cookies.c b/src/inner_cookies.c
index 4cbe659..d9035c4 100644
--- a/src/cookies.c
+++ b/src/inner_cookies.c
@@ -1,5 +1,5 @@
/* * * TODO * * */
-#include "cookies.h"
+#include "inner_cookies.h"
#include "utils.h"
#include <stdlib.h>
diff --git a/src/inner_cookies.h b/src/inner_cookies.h
new file mode 100644
index 0000000..c336cf7
--- /dev/null
+++ b/src/inner_cookies.h
@@ -0,0 +1,10 @@
+#ifndef MAGI_INCLUDED_INNER_COOKIES
+#define MAGI_INCLUDED_INNER_COOKIES
+
+#include "request.h"
+
+
+void magi_cookies(magi_request *request, const char *data);
+
+
+#endif
diff --git a/src/multipart.c b/src/inner_multipart.c
index 7b829d8..65252e5 100644
--- a/src/multipart.c
+++ b/src/inner_multipart.c
@@ -1,5 +1,5 @@
/* Support for multifile controls are not provided. */
-#include "multipart.h"
+#include "inner_multipart.h"
#include "error.h"
#include "param.h"
diff --git a/src/inner_multipart.h b/src/inner_multipart.h
new file mode 100644
index 0000000..c3f7b65
--- /dev/null
+++ b/src/inner_multipart.h
@@ -0,0 +1,13 @@
+#ifndef MAGI_INCLUDED_INNER_MULTIPART
+#define MAGI_INCLUDED_INNER_MULTIPART
+
+#include "request.h"
+
+
+void magi_multipart(magi_request *request,
+ char *boundary,
+ int (*next)(void *userdata),
+ void *next_userdata);
+
+
+#endif
diff --git a/src/inner_urlencoded.c b/src/inner_urlencoded.c
new file mode 100644
index 0000000..e3ea56a
--- /dev/null
+++ b/src/inner_urlencoded.c
@@ -0,0 +1,144 @@
+#include "inner_urlencoded.h"
+
+#include "inner_tools.h"
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Local Shortcuts
+ */
+/* Call only if is_hex(c). */
+static int from_hex(char c)
+{
+ if (isdigit(c)) {
+ return c - '0';
+ } else {
+ return toupper(c) - 'A' + 10;
+ }
+}
+
+static int is_hex(char c)
+{
+ return isdigit(c) || strchr("ABCDEF", toupper(c));
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * URL Decoding
+ */
+static int deurl(char ** data)
+{
+ char * val = *data;
+ int ti;
+ int ci;
+ if (!val) {
+ *data = malloc(1);
+ **data = 0;
+ return 1;
+ }
+ for (ti = 0, ci = 0; 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]); /* 0000xxxx */
+ val[ti] |= from_hex(val[ci + 1]) << 4; /* XXXXxxxx */
+ ci += 2; /* Two extra characters are readed from code. */
+ } else {
+ return 0;
+ }
+ } else if (val[ci] == '+') {
+ val[ti] = ' ';
+ } else {
+ val[ti] = val[ci];
+ }
+ }
+ val[ti] = 0;
+ return 1;
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Urlencoded Automata
+ */
+enum st { st_error = 0, st_name, st_data };
+
+struct automata {
+ struct magi_param_list ** list;
+ struct magi_param param;
+ int size;
+ int len;
+};
+
+
+static enum st parse_name(struct automata * a, char c)
+{
+ if (c == '&' || c == ';') { /* Impossible character means error. */
+ return st_error;
+ }
+ if (c == '=') { /* Separator ends name. */
+ a->size = 1;
+ a->len = 0;
+ return st_data;
+ }
+
+ if (!magi_str_add(&a->param.name, &a->len, &a->size, c)) {
+ return st_error;
+ }
+ return st_name;
+}
+
+static enum st end_data(struct automata * a)
+{
+ if (deurl(&a->param.name) && deurl(&a->param.data)) {
+ if (magi_param_list_add(a->list, &a->param)) {
+ a->size = 1;
+ a->len = 0;
+ a->param.name = 0;
+ a->param.data = 0;
+ return st_name;
+ }
+ }
+ return st_error;
+}
+
+static enum st parse_data(struct automata * a, char c)
+{
+ if (c == '=') { /* Impossible character means error. */
+ return st_error;
+ }
+ if (c == '&' || c == ';') { /* Separator ends data. */
+ return end_data(a);
+ }
+
+ if (!magi_str_add(&a->param.data, &a->len, &a->size, c)) {
+ return st_error;
+ }
+ return st_data;
+}
+
+void magi_urlencoded(struct magi_param_list ** list,
+ struct magi_request * request,
+ const char * encoded)
+{
+ enum st state;
+ struct automata a = { 0, { 0, 0 }, 1, 0 };
+ a.list = list;
+ *list = 0;
+ if (!encoded || !*encoded) {
+ return;
+ }
+ for (state = st_name; state && *encoded; ++encoded) {
+ if (state == st_name) {
+ state = parse_name(&a, *encoded);
+ } else {
+ state = parse_data(&a, *encoded);
+ }
+ }
+ if (state == st_name || !state || !end_data(&a)) {
+ free(a.param.name);
+ free(a.param.data);
+ request->error = magi_error_urlenc;
+ }
+}
diff --git a/src/inner_urlencoded.h b/src/inner_urlencoded.h
new file mode 100644
index 0000000..e07ed6f
--- /dev/null
+++ b/src/inner_urlencoded.h
@@ -0,0 +1,13 @@
+#ifndef MAGI_INCLUDED_INNER_URLENCODED
+#define MAGI_INCLUDED_INNER_URLENCODED
+
+#include "request.h"
+
+
+/* Fills request->url_params via parsing encoded data. */
+void magi_urlencoded(magi_param_list **list,
+ magi_request *request,
+ const char *encoded);
+
+
+#endif
diff --git a/src/magi.h b/src/magi.h
new file mode 100644
index 0000000..b7df63c
--- /dev/null
+++ b/src/magi.h
@@ -0,0 +1,16 @@
+#ifndef MAGI_INCLUDED
+#define MAGI_INCLUDED
+/* Magi Header Collection
+ * You can include this, if you don't want to think about headers.
+ */
+#include "cgi.h"
+#include "cookie.h"
+#include "error.h"
+#include "fastcgi.h"
+#include "file.h"
+#include "param.h"
+#include "request.h"
+#include "response.h"
+#include "urlenc.h"
+
+#endif
diff --git a/src/multipart.h b/src/multipart.h
deleted file mode 100644
index 47cfefe..0000000
--- a/src/multipart.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef MAGI_INCLUDED_MULTIPART
-#define MAGI_INCLUDED_MULTIPART
-
-#include "request.h"
-
-
-void magi_multipart(struct magi_request * request,
- char * boundary,
- int (*next)(void * userdata),
- void * next_userdata);
-
-
-#endif
diff --git a/src/param.h b/src/param.h
index 3f8cefe..bebacd7 100644
--- a/src/param.h
+++ b/src/param.h
@@ -2,27 +2,27 @@
#define MAGI_INCLUDED_PARAM
-struct magi_param {
+typedef struct magi_param {
/* All pointers must be valid as 'free' arguments. */
- char * name;
- char * data;
-};
+ char *name;
+ char *data;
+} magi_param;
-struct magi_param_list {
- struct magi_param_list * next; /* Must be valid as 'free' argument. */
- struct magi_param item;
-};
+typedef struct magi_param_list {
+ struct magi_param_list *next; /* Must be valid as 'free' argument. */
+ magi_param item;
+} magi_param_list;
/* Addition of item to top of list. Null <=> error. */
-int magi_param_list_add(struct magi_param_list ** list,
- struct magi_param * item);
+int magi_param_list_add(magi_param_list **list,
+ magi_param *item);
/* Data of the first node in list: node.name == name; else null. */
-char * magi_param_list_get(struct magi_param_list * list, const char * name);
+char *magi_param_list_get(magi_param_list *list, const char *name);
/* Freeing and invalidation of list. */
-void magi_param_list_destroy(struct magi_param_list * list);
+void magi_param_list_destroy(magi_param_list *list);
#endif
diff --git a/src/request.h b/src/request.h
index be92370..ffa239f 100644
--- a/src/request.h
+++ b/src/request.h
@@ -27,75 +27,91 @@
* document_uri: {script_name}{path_info}
* /bin/script /article/magic
*/
-struct magi_request {
+typedef struct magi_request {
/* * * Results * * */
/* All pointers of this section must be valid as 'free' arguments. */
/* 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 * params; /* Parameters from 'post' body */
- struct magi_file_list * files; /* 'Post' multipart files */
+ magi_cookie_list *cookies;
+ magi_param_list *http_params; /* HTTP Header parameters */
+ magi_param_list *url_params; /* Paramteres from URL */
+ magi_param_list *params; /* Parameters from 'post' body */
+ magi_file_list *files; /* 'Post' multipart files */
/* Environment Shortcuts */
- char * method; /* REQUEST_METHOD */
- char * uri; /* REQUEST_URI */
- char * document_root; /* DOCUMENT_ROOT */
- char * document_uri; /* DOCUMENT_URI */
- char * script_name; /* SCRIPT_NAME */
- char * script_filename; /* SCRIPT_FILENAME */
- char * remote_addr; /* REMOTE_ADDR */
- char * remote_port; /* REMOTE_PORT */
- char * server_addr; /* SERVER_ADDR */
- char * server_name; /* SERVER_NAME */
+ char *method; /* REQUEST_METHOD */
+ char *uri; /* REQUEST_URI */
+ char *document_root; /* DOCUMENT_ROOT */
+ char *document_uri; /* DOCUMENT_URI */
+ char *script_name; /* SCRIPT_NAME */
+ char *script_filename; /* SCRIPT_FILENAME */
+ char *remote_addr; /* REMOTE_ADDR */
+ char *remote_port; /* REMOTE_PORT */
+ char *server_addr; /* SERVER_ADDR */
+ char *server_name; /* SERVER_NAME */
/* server_name can be not a domain name, even if request is done with it.
* (Use http_params["HTTP_HOST"] instead.) */
- char * server_port; /* SERVER_PORT */
- char * server_protocol; /* SERVER_PROTOCOL */
- char * server_software; /* SERVER_COFTWARE */
- char * path_info; /* PATH_INFO */
+ char *server_port; /* SERVER_PORT */
+ char *server_protocol; /* SERVER_PROTOCOL */
+ char *server_software; /* SERVER_COFTWARE */
+ char *path_info; /* PATH_INFO */
/* Request Error Code */
- enum magi_error error;
+ magi_error error;
/* * * Settings * * */
/* Callback for processing files */
- void (*file_callback)(struct magi_file * file,
- char * addon,
- int addon_len,
- int is_addon_last,
- void * userdata);
- void * file_callback_userdata;
- int file_callback_addon_max;
+ void (*file_callback)(magi_file *file,
+ char *addon,
+ int addon_len,
+ int is_addon_last,
+ void *userdata);
+ void *file_callback_userdata;
+ int file_callback_addon_max;
/* Limits for memory used (null <=> unlimitted) */
int cookies_max;
int url_params_max;
int http_params_max;
int params_max;
-};
+} 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_request_setup(magi_request *request);
+
+
+/* Destroys request. */
+void magi_request_destroy(magi_request *request);
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Tempfiles Callback
+ */
+typedef 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. */
+} magi_tempfile;
+
+typedef struct magi_tempfiles {
+ int count;
+ magi_tempfile *tmps;
+} magi_tempfiles;
+
+void magi_tempfiles_add(magi_tempfiles *tmps,
+ const char *name,
+ const char *path,
+ int max);
+
+void magi_tempfiles_destroy(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);
+void magi_request_setup_tempfiles(magi_request *request,
+ magi_tempfiles *table);
/* Destroys request. */
void magi_request_destroy(struct magi_request * request);
diff --git a/src/response.c b/src/response.c
index 7e2ec0b..e4cd342 100644
--- a/src/response.c
+++ b/src/response.c
@@ -6,33 +6,33 @@
#include <stdlib.h>
#include <string.h>
-int vsnprintf(char * s, size_t n, const char * format, va_list arg);
+/* TODO: realise vsnprintf or eliminate need of it. (see musl) */
+int vsnprintf(char *s, size_t n, const char *format, va_list arg);
-void magi_response_setup(struct magi_response * response)
+void magi_response_setup(magi_response *response)
{
response->cookies = 0;
response->http_params = 0;
response->content_type = 0;
+ magi_response_content_type(response, "application/xhtml+xml");
response->content = magi_str_create(0);
response->len = 0;
response->size = 1;
}
-
-void magi_response_content_type(struct magi_response * response,
- enum magi_content_type type)
+void magi_response_content_type(magi_response *response, const char *type)
{
- const char * const messages[] = {
- "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);
- }
+ static const char *const ct = "Content-Type: ";
+ static const int ctlen = 15;
+ const int len = strlen(type);
+ free(response->content_type);
+ response->content_type = malloc(ctlen + len + 1);
+ memcpy(response->content_type, ct, ctlen);
+ memcpy(response->content_type + ctlen, type, len + 1);
}
-void magi_response_add(struct magi_response * r, const char * addon)
+void magi_response_add(magi_response *r, const char *addon)
{
int addon_len;
if (!addon) {
@@ -46,11 +46,9 @@ void magi_response_add(struct magi_response * r, const char * addon)
r->len += addon_len;
}
-void magi_response_add_format(struct magi_response * response,
- const char * addon,
- ...)
+void magi_response_add_format(magi_response *response, const char *addon, ...)
{
- char * act_addon;
+ char *act_addon;
int n;
va_list args;
va_start(args, addon);
@@ -66,34 +64,36 @@ void magi_response_add_format(struct magi_response * response,
}
}
-void magi_response_cookie(struct magi_response * response,
- struct magi_cookie * cookie)
+void magi_response_cookie(magi_response *response, magi_cookie *cookie)
{
magi_cookie_list_add(&response->cookies, cookie);
}
-void magi_response_cookie_easy(struct magi_response * response,
- const char * name,
- const char * value)
+void magi_response_cookie_easy(magi_response *response,
+ const char *name,
+ const char *value)
+{
+
+void magi_response_cookie_discard(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.data = magi_str_create_copy(value, value + strlen(value));
+ magi_cookie cookie = { 0, 0, 0, 0, 0 };
+ 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);
}
-void magi_response_http(struct magi_response * response,
- const char * name,
- const char * data)
+void magi_response_http(magi_response *response,
+ const char *name,
{
- 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));
+ magi_param param = { 0, 0 };
+ 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, &param);
}
-void magi_response_destroy(struct magi_response * response)
+void magi_response_destroy(magi_response *response)
{
if (!response) {
return;
diff --git a/src/response.h b/src/response.h
index 95f6537..a51d4a4 100644
--- a/src/response.h
+++ b/src/response.h
@@ -5,42 +5,39 @@
#include "param.h"
-enum magi_content_type { magi_xhtml = 0 };
+typedef struct magi_response {
+ magi_cookie_list *cookies;
+ magi_param_list *http_params;
+ char *content_type;
+ char *content;
+ int len;
+ int size;
+} magi_response;
-struct magi_response {
- struct magi_cookie_list * cookies;
- struct magi_param_list * http_params;
- char * content_type;
- char * content;
- int len;
- int size;
-};
+void magi_response_setup(magi_response *response);
-void magi_response_setup(struct magi_response * response);
+void magi_response_content_type(magi_response *response, const char *type);
-void magi_response_content_type(struct magi_response * response,
- enum magi_content_type type);
+void magi_response_add(magi_response *response, const char *addon);
+void magi_response_add_format(magi_response *response, const char *addon, ...);
-void magi_response_add(struct magi_response * response, const char * addon);
-void magi_response_add_format(struct magi_response * response,
- const char * addon,
- ...);
+void magi_response_cookie(magi_response *response, magi_cookie *cookie);
-void magi_response_cookie(struct magi_response * response,
- struct magi_cookie * cookie);
+void magi_response_cookie_easy(magi_response *response,
+ const char *name,
+ const char *value);
-void magi_response_cookie_easy(struct magi_response * response,
- const char * name,
- const char * value);
+void magi_response_cookie_discard(magi_response *response,
+ const char *name);
-void magi_response_http(struct magi_response * response,
- const char * name,
- const char * data);
+void magi_response_http(magi_response *response,
+ const char *name,
+ const char *data);
-void magi_response_destroy(struct magi_response * response);
+void magi_response_destroy(magi_response *response);
#endif
diff --git a/src/urlenc.c b/src/urlenc.c
index 8c38a0a..bb0bada 100644
--- a/src/urlenc.c
+++ b/src/urlenc.c
@@ -2,23 +2,12 @@
#include "utils.h"
#include <ctype.h>
-#include <stdlib.h>
#include <string.h>
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Local Shortcuts
*/
-/* Call only if is_hex(c). */
-static int from_hex(char c)
-{
- if (isdigit(c)) {
- return c - '0';
- } else {
- return toupper(c) - 'A' + 10;
- }
-}
-
/* Call only if 0 <= num && num <= 15. */
static char to_hex(int num)
{
@@ -26,11 +15,6 @@ static char to_hex(int num)
return hex[num];
}
-static int is_hex(char c)
-{
- return isdigit(c) || strchr("ABCDEF", toupper(c));
-}
-
static int is_url(char c)
{
return isalnum(c) || strchr("$-_.+ !*'(),", c);
@@ -38,125 +22,6 @@ static int is_url(char c)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * URL Decoding
- */
-static int deurl(char ** data)
-{
- char * val = *data;
- int ti;
- int ci;
- if (!val) {
- *data = malloc(1);
- **data = 0;
- return 1;
- }
- for (ti = 0, ci = 0; 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]); /* 0000xxxx */
- val[ti] |= from_hex(val[ci + 1]) << 4; /* XXXXxxxx */
- ci += 2; /* Two extra characters are readed from code. */
- } else {
- return 0;
- }
- } else if (val[ci] == '+') {
- val[ti] = ' ';
- } else {
- val[ti] = val[ci];
- }
- }
- val[ti] = 0;
- return 1;
-}
-
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Urlencoded Automata
- */
-enum st { st_error = 0, st_name, st_data };
-
-struct automata {
- struct magi_param_list ** list;
- struct magi_param param;
- int size;
- int len;
-};
-
-
-static enum st parse_name(struct automata * a, char c)
-{
- if (c == '&' || c == ';') { /* Impossible character means error. */
- return st_error;
- }
- if (c == '=') { /* Separator ends name. */
- a->size = 1;
- a->len = 0;
- return st_data;
- }
-
- if (!magi_str_add(&a->param.name, &a->len, &a->size, c)) {
- return st_error;
- }
- return st_name;
-}
-
-static enum st end_data(struct automata * a)
-{
- if (deurl(&a->param.name) && deurl(&a->param.data)) {
- if (magi_param_list_add(a->list, &a->param)) {
- a->size = 1;
- a->len = 0;
- a->param.name = 0;
- a->param.data = 0;
- return st_name;
- }
- }
- return st_error;
-}
-
-static enum st parse_data(struct automata * a, char c)
-{
- if (c == '=') { /* Impossible character means error. */
- return st_error;
- }
- if (c == '&' || c == ';') { /* Separator ends data. */
- return end_data(a);
- }
-
- if (!magi_str_add(&a->param.data, &a->len, &a->size, c)) {
- return st_error;
- }
- return st_data;
-}
-
-void magi_urlenc(struct magi_param_list ** list,
- struct magi_request * request,
- const char * encoded)
-{
- enum st state;
- struct automata a = { 0, { 0, 0 }, 1, 0 };
- a.list = list;
- *list = 0;
- if (!encoded || !*encoded) {
- return;
- }
- for (state = st_name; state && *encoded; ++encoded) {
- if (state == st_name) {
- state = parse_name(&a, *encoded);
- } else {
- state = parse_data(&a, *encoded);
- }
- }
- if (state == st_name || !state || !end_data(&a)) {
- free(a.param.name);
- free(a.param.data);
- request->error = magi_error_urlenc;
- }
-}
-
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* URL Encoding
*/
int magi_urlenc_size(const char * plain)
diff --git a/src/urlenc.h b/src/urlenc.h
index 5240109..edaec08 100644
--- a/src/urlenc.h
+++ b/src/urlenc.h
@@ -1,17 +1,10 @@
#ifndef MAGI_INCLUDED_URLENC
#define MAGI_INCLUDED_URLENC
-#include "request.h"
-
-/* Fills request->url_params via parsing encoded data. */
-void magi_urlenc(struct magi_param_list ** list,
- struct magi_request * request,
- const char * encoded);
-
-/* 'code' from urlencode must have size of at least magi_urlenc_size(plain). */
-int magi_urlenc_size(const char * plain);
-void magi_urlencode(const char * plain, char * code);
+/* 'code' from urlenc must have size of at least magi_urlenc_size(plain). */
+int magi_urlenc_size(const char *plain);
+void magi_urlenc(const char *plain, char *code);
#endif