From a93c561921b79e5f27b986292fe70dce1879f91e Mon Sep 17 00:00:00 2001
From: Aleksey Veresov <aleksey@veresov.pro>
Date: Fri, 21 Feb 2020 18:09:22 +0300
Subject: [magi]

---
 Makefile                |  33 ++++++------
 examples/Makefile       |  11 ++--
 examples/fcgi.c         |   2 +-
 include/magi/loadfile.h |  31 +++++++++++
 include/magi/request.h  |  27 ----------
 readme                  |   9 ++--
 src/cgi.c               |   8 +--
 src/cookies.c           |   4 +-
 src/error.c             |   4 +-
 src/loadfile.c          |  77 ++++++++++++++++++++++++++
 src/multipart.c         |   4 +-
 src/request.c           |  77 --------------------------
 src/tools.c             |  25 +++++----
 src/tools.h             |  14 ++---
 src/urlenc.c            |   2 +-
 src/urlencoded.c        | 140 +++++++++++++++++++++++-------------------------
 src/urlencoded.h        |  13 +++--
 17 files changed, 237 insertions(+), 244 deletions(-)
 create mode 100644 include/magi/loadfile.h
 create mode 100644 src/loadfile.c

diff --git a/Makefile b/Makefile
index f25e658..93f4a2d 100644
--- a/Makefile
+++ b/Makefile
@@ -1,9 +1,10 @@
-### TODO: Partial compilation (e.g. cgi+urlenc, but without fcgi)
 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
 #     Compilation Options
 # Debug mode (allowing to debug the library via gdb):
 # DEBUG   = yes
-# Specify your favourite C compiler here (e.g. tcc):
+# Optional modules (remove unwanted ones):
+MODULES = cgi fastcgi loadfile urlenc
+# Specify your favourite C compiler here:
 CC      = gcc
 
 
@@ -20,9 +21,17 @@ else
 CFLAGS += -O3
 endif
 
+# Interfacial files to compile:
+INTER   = cookie error file param request response $(MODULES)
+
 # Object files listing:
+INC_DIR = include/magi
 SRC_DIR = src
-SRC     = $(wildcard $(SRC_DIR)/*.c)
+INTER_H = $(foreach name,$(INTER),$(INC_DIR)/$(name).h)
+INTER_C = $(foreach name,$(INTER),$(SRC_DIR)/$(name).c)
+INNER_H = $(wildcard $(SRC_DIR)/*.h)
+INNER_C = $(INNER_H:.h=.c)
+SRC     = $(INTER_C) $(INNER_C)
 OBJ     = $(SRC:.c=.o)
 
 
@@ -33,27 +42,15 @@ default: $(LIB)
 
 # Cleaning means removing everything automatically produced:
 clean:
-	rm -f $(OBJ) $(LIB) deps.mk
+	rm -f $(OBJ) $(LIB)
 
 
 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
 #     Compilation
 # Compile object files from corresponding source and header:
-%.o: %.c %.h
-	$(CC) $(CFLAGS) -c $< -o $@
+%.o: %.c
+	$(CC) $(CFLAGS) -I $(INC_DIR) -c $< -o $@
 
 # Packing object files into library:
 $(LIB): $(OBJ)
 	ar rcs $@ $^
-
-
-# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
-#     Dependencies
-# Generating dependencies description file:
-deps.mk: $(SRC)
-	$(CC) -MM $^ > $@
-
-# While cleaning we need to remove it, not include:
-ifneq "clean" "$(MAKECMDGOALS)"
--include deps.mk
-endif
diff --git a/examples/Makefile b/examples/Makefile
index 8f5282c..28e9bed 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -2,14 +2,14 @@
 #     Compilation Options
 # Debug mode (allowing to debug the examples via gdb):
 # DEBUG    = yes
+# Examples to build by default:
+EXAMPLES = append cookie upload echo
 # Specify your favourite C compiler here (e.g. tcc):
 CC       = gcc
 
 
 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
 #     Preparations
-EXAMPLES = append cookie upload echo
-
 # Compile under the most strict conditions:
 CFLAGS   = -xc -ansi -pedantic -Wall
 # Debug and optimisation are not compatible:
@@ -22,8 +22,7 @@ endif
 # Including magi library headers and setting linker to use it:
 INCLUDE  = -I ../include
 LFLAGS   = -L.. -lmagi
-
-# Specification of library file to produce it, if not provided:
+# Specify library file to set it as a prerequisite for compilation:
 MAGI     = ../libmagi.a
 
 
@@ -42,7 +41,3 @@ clean:
 # Compile executables from corresponding sources and library:
 %: %.c $(MAGI)
 	$(CC) $(CFLAGS) $(INCLUDE) $< $(LFLAGS) -o $@
-
-# Run make for library to produce it:
-$(MAGI):
-	cd ..; $(MAKE)
diff --git a/examples/fcgi.c b/examples/fcgi.c
index bb5645e..de2f525 100644
--- a/examples/fcgi.c
+++ b/examples/fcgi.c
@@ -1,4 +1,4 @@
-/* * * TODO * * */
+/* * * TODO -- not valid yet * * */
 #include <magi.h>
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/include/magi/loadfile.h b/include/magi/loadfile.h
new file mode 100644
index 0000000..942c298
--- /dev/null
+++ b/include/magi/loadfile.h
@@ -0,0 +1,31 @@
+#ifndef MAGI_INCLUDED_LOADFILE
+#define MAGI_INCLUDED_LOADFILE
+
+#include "request.h"
+
+
+typedef struct magi_loadfile {
+    const char *param_name; /* Form field name, in which file is expected. */
+    const char *location;   /* Location to load file in. */
+    int         maximum;    /* Limit in bytes. Null <=> unlimited. */
+} magi_loadfile;
+
+typedef struct magi_loadfiles {
+    int            count;
+    magi_loadfile *files;
+} magi_loadfiles;
+
+void magi_loadfiles_add(magi_loadfiles *table,
+                        const char     *name,
+                        const char     *path,
+                        int             max);
+
+void magi_loadfiles_destroy(magi_loadfiles *table);
+
+/* Setup request callback with files loaded into corresponding to their
+ * parameter names locations; paths are in magi_loadfiles struct. */
+void magi_request_setup_loadfiles(magi_request   *request,
+                                  magi_loadfiles *table);
+
+
+#endif
diff --git a/include/magi/request.h b/include/magi/request.h
index b15f085..47acb27 100644
--- a/include/magi/request.h
+++ b/include/magi/request.h
@@ -89,31 +89,4 @@ void magi_request_setup(magi_request *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(magi_request   *request,
-                                  magi_tempfiles *table);
-
-
 #endif
diff --git a/readme b/readme
index fb36636..3160155 100644
--- a/readme
+++ b/readme
@@ -4,11 +4,12 @@ Magi Library (libmagi) implements Gateway Interfaces, namely CGI and FastCGI.
     Overview
 Magi are free and open-source software: legal info is in the 'license' file.
 They are written in ANSI C, without any dependecies, except for C standard
-library.  All source and header files are located in the 'src' directory.
+library.  All source and inner header files are located in the 'src' directory.
 The 'include' directory is intended to be used in your include environment.
-Headers themselves are in 'magi' subdirectory of include, due to their short
-and simple names.  If you are not about choosing which header to include and
-just want everything to be included you can use 'magi.h'.
+Headers in it contain library interface and its documentation in comments.
+They are in subdirectory 'include/magi', due to their short and simple names.
+If you are not about choosing which header to include and just want everything
+to be included you can '#include <magi.h>'.
 
     Compiling
 Compilation and its options are described in the 'Makefile'.
diff --git a/src/cgi.c b/src/cgi.c
index 20df48e..efb05c2 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 "inner_cookies.h"
-#include "inner_tools.h"
-#include "inner_multipart.h"
-#include "inner_urlencoded.h"
+#include "multipart.h"
 #include "param.h"
 #include "request.h"
+#include "tools.h"
+#include "urlencoded.h"
 #include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/src/cookies.c b/src/cookies.c
index 9dfde7a..8b610d4 100644
--- a/src/cookies.c
+++ b/src/cookies.c
@@ -1,7 +1,7 @@
 /* * *   TODO   * * */
-#include "inner_cookies.h"
+#include "cookies.h"
 
-#include "inner_tools.h"
+#include "tools.h"
 #include <stdlib.h>
 #include <string.h>
 
diff --git a/src/error.c b/src/error.c
index efe6dbf..a1c3153 100644
--- a/src/error.c
+++ b/src/error.c
@@ -1,9 +1,9 @@
 #include "error.h"
 
 
-const char * magi_error_message(enum magi_error error)
+const char *magi_error_message(magi_error error)
 {
-    const char * const messages[] = {
+    const char *const messages[] = {
         0,                             /* magi_error_none */
         "No boundary for multipart.",  /* magi_error_nobound */
         "Content-Type is unknown.",    /* magi_error_unknown */
diff --git a/src/loadfile.c b/src/loadfile.c
new file mode 100644
index 0000000..e8e0655
--- /dev/null
+++ b/src/loadfile.c
@@ -0,0 +1,77 @@
+#include "loadfile.h"
+
+#include <stdio.h>
+#include <string.h>
+
+
+void magi_loadfiles_add(magi_loadfiles *table,
+                        const char     *name,
+                        const char     *path,
+                        int             max)
+{
+    static const int size = sizeof(*table->files);
+    if (!table) {
+        return;
+    }
+    if (table->count) {
+        table->files = realloc(table->files, size * table->count + size);
+    } else {
+        table->files = malloc(size);
+    }
+    table->files[table->count].param_name = name;
+    table->files[table->count].location   = path;
+    table->files[table->count].maximum    = max;
+    table->count++;
+}
+
+void magi_loadfiles_destroy(magi_loadfiles *table)
+{
+    if (!table) {
+        return;
+    }
+    free(table->table);
+}
+
+static void loadfiles(magi_file *file,
+                      char      *addon,
+                      int        addon_len,
+                      int        is_addon_last,
+                      void      *userdata)
+{
+    magi_loadfiles *table = userdata;
+    int             pos;
+    if (!file->file_name || !strcmp(file->file_name, "")) {
+        return;
+    }
+    for (pos = 0; pos != table->count; ++pos) {
+        if (!strcmp(table->files[pos].param_name, file->param_name)) {
+            static FILE *f = 0;
+            static int   unlimited;
+            static int   left;
+            if (!f) {
+                const char * loc = table->files[pos].location;
+                f                = fopen(loc, "wb");
+                left             = table->files[pos].maximum;
+                unlimited        = !left;
+            }
+            if (unlimited) {
+                fwrite(addon, 1, addon_len, f);
+            } else {
+                int min = left < addon_len ? left : addon_len;
+                fwrite(addon, 1, min, f);
+                left -= min;
+            }
+            if (is_addon_last) {
+                fclose(f);
+                f = 0;
+            }
+            return;
+        }
+    }
+}
+
+void magi_request_setup_loadfiles(magi_request *request, magi_loadfiles *table)
+{
+    request->file_callback          = loadfiles;
+    request->file_callback_userdata = table;
+}
diff --git a/src/multipart.c b/src/multipart.c
index 0187f7c..001b4d1 100644
--- a/src/multipart.c
+++ b/src/multipart.c
@@ -1,9 +1,9 @@
 /* Support for multifile controls are not provided. */
-#include "inner_multipart.h"
+#include "multipart.h"
 
 #include "error.h"
-#include "inner_tools.h"
 #include "param.h"
+#include "tools.h"
 #include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/src/request.c b/src/request.c
index 8c3a101..3677eb7 100644
--- a/src/request.c
+++ b/src/request.c
@@ -3,9 +3,7 @@
 #include "cookie.h"
 #include "file.h"
 #include "param.h"
-#include <stdio.h>
 #include <stdlib.h>
-#include <string.h>
 
 
 void magi_request_setup(struct magi_request * request)
@@ -80,78 +78,3 @@ void magi_request_destroy(struct magi_request * request)
         request_annul(request);
     }
 }
-
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Tempfiles Callback
- */
-void magi_tempfiles_add(struct magi_tempfiles * tmps,
-                        const char *            name,
-                        const char *            path,
-                        int                     max)
-{
-    if (!tmps) {
-        return;
-    }
-    if (tmps->count++) {
-        tmps->tmps = realloc(tmps->tmps, sizeof(*tmps->tmps) * tmps->count);
-    } else {
-        tmps->tmps = malloc(sizeof(*tmps->tmps));
-    }
-    tmps->tmps[tmps->count - 1].param_name = name;
-    tmps->tmps[tmps->count - 1].location   = path;
-    tmps->tmps[tmps->count - 1].maximum    = max;
-}
-
-void magi_tempfiles_destroy(struct magi_tempfiles * tmps)
-{
-    if (!tmps) {
-        return;
-    }
-    free(tmps->tmps);
-}
-
-static void tempfiles(struct magi_file * file,
-                      char *             addon,
-                      int                addon_len,
-                      int                is_addon_last,
-                      void *             userdata)
-{
-    struct magi_tempfiles * table = userdata;
-    int                     pos;
-    if (!file->file_name || !strcmp(file->file_name, "")) {
-        return;
-    }
-    for (pos = 0; pos != table->count; ++pos) {
-        if (!strcmp(table->tmps[pos].param_name, file->param_name)) {
-            static FILE * f = 0;
-            static int    unlimited;
-            static int    left;
-            if (!f) {
-                const char * loc = table->tmps[pos].location;
-                f                = fopen(loc, "wb");
-                left             = table->tmps[pos].maximum;
-                unlimited        = !left;
-            }
-            if (unlimited) {
-                fwrite(addon, 1, addon_len, f);
-            } else {
-                int min = left < addon_len ? left : addon_len;
-                fwrite(addon, 1, min, f);
-                left -= min;
-            }
-            if (is_addon_last) {
-                fclose(f);
-                f = 0;
-            }
-            return;
-        }
-    }
-}
-
-void magi_request_setup_tempfiles(struct magi_request *   request,
-                                  struct magi_tempfiles * table)
-{
-    request->file_callback          = tempfiles;
-    request->file_callback_userdata = table;
-}
diff --git a/src/tools.c b/src/tools.c
index d958851..ecfcd6c 100644
--- a/src/tools.c
+++ b/src/tools.c
@@ -1,4 +1,4 @@
-#include "inner_tools.h"
+#include "tools.h"
 
 #include <ctype.h>
 #include <stdlib.h>
@@ -33,19 +33,22 @@ char *magi_str_create(int len)
     return str;
 }
 
-int magi_str_add(char **dest, int *len, int *size, char c)
+int magi_str_add(magi_str *str, char c)
 {
-    if (!*dest) {
-        *dest = magi_str_create(1);
-    } else if (*len + 1 == *size) {
-        *size *= 2;
-        *dest  = realloc(*dest, *size);
+    if (!str->data) {
+        str->len  = 0;
+        str->size = 2;
+        str->data = malloc(2);
+    } else if (str->len + 1 == str->size) {
+        str->size *= 2;
+        str->data  = realloc(str->data, str->size);
     }
-    if (!*dest) {
+    if (!str->dest) {
+        str->len  = 0;
+        str->size = 0;
         return 0;
     }
-    (*dest)[*len] = c;
-    ++*len;
-    (*dest)[*len] = 0;
+    str->data[str->len++] = c;
+    str->data[str->len]   = 0;
     return 1;
 }
diff --git a/src/tools.h b/src/tools.h
index 8d66131..f7e701d 100644
--- a/src/tools.h
+++ b/src/tools.h
@@ -1,9 +1,5 @@
 #ifndef MAGI_INCLUDED_TOOLS
 #define MAGI_INCLUDED_TOOLS
-/* * Collection of helpful functions for internal use.
- *
- * blah...
- */
 
 
 void magi_str_lowercase(char *str);
@@ -12,8 +8,14 @@ void magi_str_lowercase(char *str);
 char *magi_str_create_copy(const char *first, int len);
 char *magi_str_create(int len);
 
-/* Null only in case of error; if *dest is null creates string. */
-int magi_str_add(char **dest, int *len, int *size, char c);
+
+typedef struct magi_str {
+    char *data;
+    int   size;
+    int   len;
+} magi_str;
+
+int magi_str_add(magi_str *str, char c);
 
 
 #endif
diff --git a/src/urlenc.c b/src/urlenc.c
index 64a087e..28fbd48 100644
--- a/src/urlenc.c
+++ b/src/urlenc.c
@@ -1,6 +1,6 @@
 #include "urlenc.h"
 
-#include "inner_tools.h"
+#include "tools.h"
 #include <ctype.h>
 #include <string.h>
 
diff --git a/src/urlencoded.c b/src/urlencoded.c
index e3ea56a..9d596ed 100644
--- a/src/urlencoded.c
+++ b/src/urlencoded.c
@@ -1,6 +1,6 @@
-#include "inner_urlencoded.h"
+#include "urlencoded.h"
 
-#include "inner_tools.h"
+#include "tools.h"
 #include <ctype.h>
 #include <stdlib.h>
 #include <string.h>
@@ -9,30 +9,30 @@
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * Local Shortcuts
  */
+ static int is_hex(char c)
+{
+    return isdigit(c) || strchr("abcdef", tolower(c));
+}
+
 /* Call only if is_hex(c). */
 static int from_hex(char c)
 {
     if (isdigit(c)) {
         return c - '0';
     } else {
-        return toupper(c) - 'A' + 10;
+        return tolower(c) - 'a' + 10;
     }
 }
 
-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)
 {
-    char * val = *data;
-    int    ti;
-    int    ci;
+    char *val = *data;
+    int   ti;
+    int   ci;
     if (!val) {
         *data  = malloc(1);
         **data = 0;
@@ -40,14 +40,13 @@ static int deurl(char ** data)
     }
     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 {
+            if (!is_hex(val[ci + 1]) || !is_hex(val[ci + 2])) {
                 return 0;
             }
+            /* Since chars can be signed, arithmetics are not safe. */
+            val[ti] = from_hex(val[ci + 2]) |     /* 0000xxxx */
+                      from_hex(val[ci + 1]) << 4; /* XXXXxxxx */
+            ci += 2; /* Two extra characters are readed from code. */
         } else if (val[ci] == '+') {
             val[ti] = ' ';
         } else {
@@ -62,83 +61,76 @@ static int deurl(char ** data)
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * 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)
+typedef struct automata {
+    magi_param_list **list;
+    magi_str          name;
+    magi_str          data;
+} automata;
+typedef void *(*state)(automata *a, char c);
+
+static void *state_parse_data(automata *a, char c);
+static void *state_parse_name(automata *a, char c)
 {
-    if (c == '&' || c == ';') { /* Impossible character means error. */
-        return st_error;
+    if (c == '&' || c == ';') {
+        return 0;
     }
-    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;
+    if (c == '=') {
+        if (!deurl(&a->name.data)) {
+            return 0;
+        }
+        return state_parse_name;
     }
-    return st_name;
+    magi_str_add(&a->name, c);
+    return a->name.size ? state_parse_name : 0;
 }
 
-static enum st end_data(struct automata * a)
+static int add_to_list(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;
-        }
+    magi_param param;
+    param.name = a->name.data;
+    param.data = a->data.data;
+    if (!magi_param_list_add(a->list, param)) {
+        return 0;
     }
-    return st_error;
+    a->name.data = 0;
+    a->data.data = 0;
+    return 1;
 }
 
-static enum st parse_data(struct automata * a, char c)
+static void state_parse_data(automata *a, char c)
 {
-    if (c == '=') { /* Impossible character means error. */
-        return st_error;
+    if (c == '=') {
+        return 0;
     }
-    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;
+    if (c == '&' || c == ';') {
+        if (!deurl(&a->data.data) || !add_to_list(a)) {
+            return 0;
+        }
+        return state_parse_name;
     }
-    return st_data;
+    magi_str_add(&a->data, c);
+    return a->data.size ? state_parse_data : 0;
 }
 
-void magi_urlencoded(struct magi_param_list ** list,
-                     struct magi_request *     request,
-                     const char *              encoded)
+magi_error magi_urlencoded(magi_param_list **list, const char *encoded)
 {
-    enum st         state;
-    struct automata a = { 0, { 0, 0 }, 1, 0 };
-    a.list            = list;
-    *list             = 0;
+    st       state;
+    automata a = { 0, { 0, 0 }, 1, 0 };
+    a.list     = list;
+    *list      = 0;
     if (!encoded || !*encoded) {
-        return;
+        return 0;
     }
-    for (state = st_name; state && *encoded; ++encoded) {
-        if (state == st_name) {
-            state = parse_name(&a, *encoded);
-        } else {
-            state = parse_data(&a, *encoded);
+    for (; *encoded; ++encoded) {
+        s = s(&a, *encoded);
+        if (!s) {
+            return auto_free(a);
         }
     }
     if (state == st_name || !state || !end_data(&a)) {
         free(a.param.name);
         free(a.param.data);
-        request->error = magi_error_urlenc;
+        return auto_free(a);
     }
+    return 0;
 }
diff --git a/src/urlencoded.h b/src/urlencoded.h
index e07ed6f..319f01e 100644
--- a/src/urlencoded.h
+++ b/src/urlencoded.h
@@ -1,13 +1,12 @@
-#ifndef MAGI_INCLUDED_INNER_URLENCODED
-#define MAGI_INCLUDED_INNER_URLENCODED
+#ifndef MAGI_INCLUDED_URLENCODED
+#define MAGI_INCLUDED_URLENCODED
 
-#include "request.h"
+#include "error.h"
+#include "param.h"
 
 
-/* Fills request->url_params via parsing encoded data. */
-void magi_urlencoded(magi_param_list **list,
-                     magi_request     *request,
-                     const char       *encoded);
+/* Add decoded params from 'encoded' to 'list'. */
+magi_error magi_urlencoded(magi_param_list **list, const char *encoded);
 
 
 #endif
-- 
cgit v1.2.3