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