aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Veresov <aleksey@veresov.pro>2019-11-06 20:18:29 +0300
committerAleksey Veresov <aleksey@veresov.pro>2019-11-06 20:18:29 +0300
commitb11b1c52280f172ebfa42c3da906ea9aa3ea8799 (patch)
treec335acbc3cea17e1edb4fbc7b8f617019c68a2da
parenta5ec437e91f90f25711c7e1b47b8238fdae6b103 (diff)
downloadmagi-b11b1c52280f172ebfa42c3da906ea9aa3ea8799.tar
magi-b11b1c52280f172ebfa42c3da906ea9aa3ea8799.tar.xz
magi-b11b1c52280f172ebfa42c3da906ea9aa3ea8799.zip
[magi] FastCGI is comming.
-rw-r--r--examples/append.c5
-rw-r--r--examples/cookie.c5
-rw-r--r--examples/echo.c7
-rw-r--r--examples/upload.c3
-rw-r--r--src/cgi.c218
-rw-r--r--src/cgi.h21
-rw-r--r--src/fastcgi.c0
-rw-r--r--src/fastcgi.h0
-rw-r--r--src/request.c248
-rw-r--r--src/request.h18
-rw-r--r--src/utils.h38
11 files changed, 292 insertions, 271 deletions
diff --git a/examples/append.c b/examples/append.c
index 65caa33..b8aa1cf 100644
--- a/examples/append.c
+++ b/examples/append.c
@@ -1,12 +1,13 @@
+#include <cgi.h>
+#include <request.h>
#include <stdio.h>
#include <stdlib.h>
-#include <request.h>
void handle_request()
{
struct magi_request request;
- if (magi_request_build_cgi(&request, 0, 0)) {
+ if (magi_cgi(&request, 0, 0)) {
struct magi_field *a = magi_field_list_get(request.fields, "addon");
if (a && a->data) {
FILE *file = fopen("file_to_append", "a");
diff --git a/examples/cookie.c b/examples/cookie.c
index 8f4018b..dd18cc6 100644
--- a/examples/cookie.c
+++ b/examples/cookie.c
@@ -1,7 +1,8 @@
+#include <cgi.h>
#include <cookie.h>
+#include <request.h>
#include <stdio.h>
#include <stdlib.h>
-#include <request.h>
void print_preamble()
@@ -26,7 +27,7 @@ void print_webpage_top()
void read_and_print_cookies()
{
struct magi_request request;
- if (magi_request_build_cgi(&request, 0, 0)) {
+ if (magi_cgi(&request, 0, 0)) {
struct magi_cookie_list *cookie;
for (cookie = request.cookies; cookie; cookie = cookie->next) {
printf(
diff --git a/examples/echo.c b/examples/echo.c
index 33094a4..ff037a6 100644
--- a/examples/echo.c
+++ b/examples/echo.c
@@ -1,8 +1,9 @@
-#include <stdio.h>
-#include <stdlib.h>
+#include <cgi.h>
#include <cookie.h>
#include <param.h>
#include <request.h>
+#include <stdio.h>
+#include <stdlib.h>
void print_preamble()
@@ -76,7 +77,7 @@ void proceed_params(struct magi_param_list *params)
void handle_request()
{
struct magi_request request;
- if (magi_request_build_cgi(&request, 0, 0)) {
+ if (magi_cgi(&request, 0, 0)) {
puts("<h1>Echo CGI Script</h1>");
puts("I was called with method [");
puts(request.method);
diff --git a/examples/upload.c b/examples/upload.c
index 1dc9659..59dd020 100644
--- a/examples/upload.c
+++ b/examples/upload.c
@@ -3,6 +3,7 @@
#include <string.h>
#include <request.h>
#include <multipart.h>
+#include <cgi.h>
void tempfile_callback(struct magi_field *field, char *buffer, int len)
{
@@ -30,7 +31,7 @@ void tempfile_callback(struct magi_field *field, char *buffer, int len)
void handle_request()
{
struct magi_request request;
- if (magi_request_build_cgi(&request, tempfile_callback, 0)) {
+ if (magi_cgi(&request, tempfile_callback, 0)) {
struct magi_field *name = magi_field_list_get(request.fields, "name");
struct magi_field *data = magi_field_list_get(request.fields, "data");
if (name && name->data && data) {
diff --git a/src/cgi.c b/src/cgi.c
new file mode 100644
index 0000000..1a318a1
--- /dev/null
+++ b/src/cgi.c
@@ -0,0 +1,218 @@
+#include "cgi.h"
+
+#include "cookie.h"
+#include "field.h"
+#include "log.h"
+#include "multipart.h"
+#include "param.h"
+#include "request.h"
+#include "urlencoded.h"
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+extern char **environ;
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * CGI Request Handling
+ */
+/* Helpers for CGI Request Handling */
+static int plain_env(char **dest, char *env_name)
+{
+ int ok = 1;
+ const char *env = getenv(env_name);
+ if (env) {
+ *dest = str_alloc(strlen(env));
+ if (*dest) {
+ strcpy(*dest, env);
+ } else {
+ ok = 0;
+ }
+ } else {
+ *dest = 0;
+ }
+ return ok;
+}
+
+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)
+{
+ 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);
+ if (param.name) {
+ memcpy(param.name, *env + 5, name_end - *env - 5);
+ param.data = str_alloc(strlen(name_end + 1));
+ if (param.data) {
+ strcpy(param.data, name_end + 1);
+ } else {
+ free(param.name);
+ }
+ }
+ if (param.name && param.data) {
+ ok = magi_param_list_add(&r->http_params, &param);
+ } else {
+ ok = 0;
+ }
+ }
+ ++env;
+ }
+ return ok;
+}
+
+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");
+ return ok;
+}
+
+static int cgi_cookies(struct magi_cookie_list **list)
+{
+ int ok = 1;
+ const char *env = getenv("HTTP_COOKIE");
+ *list = 0;
+ if (env && *env) {
+ ok = magi_parse_cookie(list, env);
+ } else {
+ *list = 0;
+ }
+ return ok;
+}
+
+static int cgi_input_get(char **input)
+{
+ int ok = 1;
+ const char *env_input = getenv("QUERY_STRING");
+ if (env_input) {
+ *input = str_alloc(strlen(env_input));
+ if (*input) {
+ strcpy(*input, env_input);
+ } else {
+ ok = 0;
+ }
+ }
+ return ok;
+}
+
+static int cgi_input_post(char **input, int max)
+{
+ int ok = 1;
+ int input_len = strtoul(getenv("CONTENT_LENGTH"), 0, 10);
+ if (input_len && (input_len < max || !max)) {
+ *input = str_alloc(input_len);
+ if (*input) {
+ if (fread(*input, 1, input_len, stdin) != input_len) {
+ ok = 0;
+ magi_log("[request:cgi] Content-length is not correct.");
+ }
+ } else {
+ ok = 0;
+ }
+ }
+ return ok;
+}
+
+static char *bound(const char *type)
+{
+ char *res = 0;
+ type = strchr(type, '=');
+ if (type) {
+ type += strspn(type, " \t") + 1;
+ if (*type == '"') {
+ ++type;
+ res = create_str(type, strchr(type, '"'));
+ } else {
+ res = create_str(type, type + strcspn(type, " \t"));
+ }
+ }
+ return res;
+}
+
+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 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");
+ if (t) {
+ if (!strncmp(t, "multipart/form-data", 19)) {
+ char *boundary = bound(t);
+ if (boundary && *boundary) {
+ ok = magi_parse_multipart(
+ &request->fields,
+ intput_getter,
+ 0,
+ boundary,
+ callback
+ );
+ } 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);
+ free(in);
+ } else {
+ ok = 0;
+ magi_log("[request:cgi] Unknown content type.");
+ }
+ } else {
+ ok = 0;
+ 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);
+ free(in);
+ }
+ }
+ if (!ok) {
+ magi_request_destroy(request);
+ }
+ return ok;
+}
diff --git a/src/cgi.h b/src/cgi.h
new file mode 100644
index 0000000..c7b173c
--- /dev/null
+++ b/src/cgi.h
@@ -0,0 +1,21 @@
+#ifndef MAGI_INCLUDED_CGI
+#define MAGI_INCLUDED_CGI
+
+#include "field.h"
+#include "request.h"
+
+
+/*
+ * Constructs request using environment variables and standart I/O;
+ * Returns null if succeed, otherwise error code.
+ */
+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
+);
+
+
+#endif
diff --git a/src/fastcgi.c b/src/fastcgi.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/fastcgi.c
diff --git a/src/fastcgi.h b/src/fastcgi.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/fastcgi.h
diff --git a/src/request.c b/src/request.c
index aa2cd9b..58eefc6 100644
--- a/src/request.c
+++ b/src/request.c
@@ -1,53 +1,9 @@
#include "request.h"
+#include "field.h"
#include "cookie.h"
-#include "log.h"
-#include "multipart.h"
#include "param.h"
-#include "urlencoded.h"
-#include <ctype.h>
-#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
-
-
-extern char **environ;
-
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Local Shortcuts
- */
-static void lowercase(char *str)
-{
- if (str) {
- while (*str) {
- *str = tolower(*str);
- ++str;
- }
- }
-}
-
-static char *create_str(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;
-}
-
-static char *str_alloc(int len)
-{
- char *str = malloc(len + 1);
- if (str) {
- str[len] = 0;
- } else {
- magi_log("[request] Cannot allocate string.");
- }
- return str;
-}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
@@ -77,205 +33,3 @@ void magi_request_destroy(struct magi_request *request)
free(request->http_params);
}
}
-
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * CGI Request Handling
- */
-/* Helpers for CGI Request Handling */
-static int plain_env(char **dest, char *env_name)
-{
- int ok = 1;
- const char *env = getenv(env_name);
- if (env) {
- *dest = str_alloc(strlen(env));
- if (*dest) {
- strcpy(*dest, env);
- } else {
- ok = 0;
- }
- } else {
- *dest = 0;
- }
- return ok;
-}
-
-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)
-{
- 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);
- if (param.name) {
- memcpy(param.name, *env + 5, name_end - *env - 5);
- param.data = str_alloc(strlen(name_end + 1));
- if (param.data) {
- strcpy(param.data, name_end + 1);
- } else {
- free(param.name);
- }
- }
- if (param.name && param.data) {
- ok = magi_param_list_add(&r->http_params, &param);
- } else {
- ok = 0;
- }
- }
- ++env;
- }
- return ok;
-}
-
-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");
- return ok;
-}
-
-static int cgi_cookies(struct magi_cookie_list **list)
-{
- int ok = 1;
- const char *env = getenv("HTTP_COOKIE");
- *list = 0;
- if (env && *env) {
- ok = magi_parse_cookie(list, env);
- } else {
- *list = 0;
- }
- return ok;
-}
-
-static int cgi_input_get(char **input)
-{
- int ok = 1;
- const char *env_input = getenv("QUERY_STRING");
- if (env_input) {
- *input = str_alloc(strlen(env_input));
- if (*input) {
- strcpy(*input, env_input);
- } else {
- ok = 0;
- }
- }
- return ok;
-}
-
-static int cgi_input_post(char **input, int max)
-{
- int ok = 1;
- int input_len = strtoul(getenv("CONTENT_LENGTH"), 0, 10);
- if (input_len && (input_len < max || !max)) {
- *input = str_alloc(input_len);
- if (*input) {
- if (fread(*input, 1, input_len, stdin) != input_len) {
- ok = 0;
- magi_log("[request:cgi] Content-length is not correct.");
- }
- } else {
- ok = 0;
- }
- }
- return ok;
-}
-
-static char *bound(const char *type)
-{
- char *res = 0;
- type = strchr(type, '=');
- if (type) {
- type += strspn(type, " \t") + 1;
- if (*type == '"') {
- ++type;
- res = create_str(type, strchr(type, '"'));
- } else {
- res = create_str(type, type + strcspn(type, " \t"));
- }
- }
- return res;
-}
-
-static int intput_getter(void *any)
-{
- return getchar();
-}
-
-
-/* Interfacial CGI Request Handling */
-int magi_request_build_cgi(
- 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");
- if (t) {
- if (!strncmp(t, "multipart/form-data", 19)) {
- char *boundary = bound(t);
- if (boundary && *boundary) {
- ok = magi_parse_multipart(
- &request->fields,
- intput_getter,
- 0,
- boundary,
- callback
- );
- } 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);
- free(in);
- } else {
- ok = 0;
- magi_log("[request:cgi] Unknown content type.");
- }
- } else {
- ok = 0;
- 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);
- free(in);
- }
- }
- if (!ok) {
- magi_request_destroy(request);
- }
- return ok;
-}
diff --git a/src/request.h b/src/request.h
index a43ba63..6b9df6e 100644
--- a/src/request.h
+++ b/src/request.h
@@ -1,7 +1,9 @@
#ifndef MAGI_INCLUDED_REQUEST
#define MAGI_INCLUDED_REQUEST
+#include "cookie.h"
#include "field.h"
+#include "param.h"
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
@@ -46,26 +48,10 @@ struct magi_request {
};
-/* Common Request Handling */
/*
* Destroys request; request is not valid after destruction.
*/
void magi_request_destroy(struct magi_request *request);
-/* CGI Request Handling */
-/*
- * Constructs request using environment variables and standart I/O;
- * Returns null if succeed, otherwise error code.
- */
-int magi_request_build_cgi(
- struct magi_request *request,
- /* Callback will be used only for fields loaded via multipart. */
- /* Null callback disables callback system. */
- void (*callback)(struct magi_field *field, char *buffer, int len),
- int max_post
-);
-
-/* TODO: FastCGI Request Handling */
-
#endif
diff --git a/src/utils.h b/src/utils.h
new file mode 100644
index 0000000..a6c0aff
--- /dev/null
+++ b/src/utils.h
@@ -0,0 +1,38 @@
+#ifndef MAGI_INCLUDED_UTILS
+#define MAGI_INCLUDED_UTILS
+
+
+static void lowercase(char *str)
+{
+ if (str) {
+ while (*str) {
+ *str = tolower(*str);
+ ++str;
+ }
+ }
+}
+
+static char *create_str(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;
+}
+
+static char *str_alloc(int len)
+{
+ char *str = malloc(len + 1);
+ if (str) {
+ str[len] = 0;
+ } else {
+ magi_log("[request] Cannot allocate string.");
+ }
+ return str;
+}
+
+
+#endif