aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Veresov <aleksey@veresov.pro>2020-02-06 11:27:59 +0300
committerAleksey Veresov <aleksey@veresov.pro>2020-02-06 11:27:59 +0300
commitfca83975899b01c62ede4258f175346b7039be3d (patch)
tree37c2bb8faf95de1252a97942a68183f795eb82a0
parent8ef310a22a54dca7a80947f83f03bc296ab298dd (diff)
parent746c3f3076fe5994f08d729aa1b958465231b0c8 (diff)
downloadmagi-fca83975899b01c62ede4258f175346b7039be3d.tar
magi-fca83975899b01c62ede4258f175346b7039be3d.tar.xz
magi-fca83975899b01c62ede4258f175346b7039be3d.zip
Merge branch 'master' into test
-rw-r--r--Makefile41
-rw-r--r--examples/Makefile31
-rw-r--r--examples/echo.c4
-rw-r--r--examples/upload.c1
-rw-r--r--license2
-rw-r--r--readme50
-rw-r--r--src/cgi.c19
-rw-r--r--src/cookie.c17
-rw-r--r--src/inner_cookies.c24
-rw-r--r--src/inner_multipart.c10
-rw-r--r--src/inner_tools.c51
-rw-r--r--src/inner_tools.h19
-rw-r--r--src/request.c142
-rw-r--r--src/request.h3
-rw-r--r--src/response.c12
-rw-r--r--src/urlenc.c2
-rw-r--r--src/utils.c50
-rw-r--r--src/utils.h15
18 files changed, 299 insertions, 194 deletions
diff --git a/Makefile b/Makefile
index 1934910..db1fefd 100644
--- a/Makefile
+++ b/Makefile
@@ -1,35 +1,58 @@
-# Debug mode:
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+# Compilation Options
+# Debug mode (allowing to debug the library via gdb):
# DEBUG = yes
-
+# Specify your favourite C compiler here (e.g. tcc):
CC = gcc
+
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+# Preparations
LIB = libmagi.a
+# Compile under the most strict conditions:
CFLAGS = -xc -ansi -pedantic -Wall
+# Debug and optimisation are not compatible:
ifeq '$(DEBUG)' 'yes'
CFLAGS += -g -O0
else
CFLAGS += -O3
endif
+# Object files listing:
SRC_DIR = src
SRC = $(wildcard $(SRC_DIR)/*.c)
OBJ = $(SRC:.c=.o)
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+# Targets
+# 'make' produces library by default:
default: $(LIB)
-ifneq "clean" "$(MAKECMDGOALS)"
--include deps.mk
-endif
+# Cleaning means removing everything automatically produced:
+clean:
+ rm -f $(OBJ) $(LIB) deps.mk
-deps.mk: $(SRC)
- $(CC) -MM $^ > $@
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+# Compilation
+# Compile object files from corresponding source and header:
%.o: %.c %.h
$(CC) $(CFLAGS) -c $< -o $@
+# Packing object files into library:
$(LIB): $(OBJ)
ar rcs $@ $^
-clean:
- rm -f $(OBJ) $(LIB) deps.mk
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+# 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 d93176b..2f57b1e 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -1,29 +1,48 @@
-# Uncomment following to enable debug mode:
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+# Compilation Options
+# Debug mode (allowing to debug the examples via gdb):
# DEBUG = yes
-
+# 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:
ifeq '$(DEBUG)' 'yes'
CFLAGS += -g -O0
else
CFLAGS += -O3
endif
+# Including magi library headers and setting linker to use it:
INCLUDE = -I ../src
LFLAGS = -L.. -lmagi
+# Specification of library file to produce it, if not provided:
MAGI = ../libmagi.a
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+# Targets
+# 'make' produces all examples by default:
default: $(EXAMPLES)
-$(MAGI):
- cd ..; $(MAKE)
+# Cleaning means removing everything automatically produced:
+clean:
+ rm -f $(EXAMPLES)
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+# Compilation
+# Compile executables from corresponding sources and library:
%: %.c $(MAGI)
$(CC) $(CFLAGS) $(INCLUDE) $< $(LFLAGS) -o $@
-clean:
- rm -f $(EXAMPLES)
+# Run make for library to produce it:
+$(MAGI):
+ cd ..; $(MAKE)
diff --git a/examples/echo.c b/examples/echo.c
index 81bdcf4..f665cd0 100644
--- a/examples/echo.c
+++ b/examples/echo.c
@@ -16,10 +16,6 @@ void proceed_cookies(magi_cookie_list *cookies, magi_response *response)
magi_response_add(response, "] for domain [");
magi_response_add(response, cookies->item.domain);
}
- if (cookies->item.port) {
- magi_response_add(response, "] for port [");
- magi_response_add(response, cookies->item.port);
- }
if (cookies->item.path) {
magi_response_add(response, "] for path [");
magi_response_add(response, cookies->item.path);
diff --git a/examples/upload.c b/examples/upload.c
index 6a3a7a4..19e045c 100644
--- a/examples/upload.c
+++ b/examples/upload.c
@@ -43,6 +43,7 @@ int main(int argc, char const *argv[])
} else {
magi_error_cgi(request.error);
}
+ magi_tempfiles_destroy(&tmps);
magi_request_destroy(&request);
return 0;
}
diff --git a/license b/license
index 8f83b9c..d89e508 100644
--- a/license
+++ b/license
@@ -1,4 +1,4 @@
-Copyright 2019 Aleksey Veresov
+Copyright 2019-2020 Aleksey Veresov
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from
diff --git a/readme b/readme
new file mode 100644
index 0000000..59dfc25
--- /dev/null
+++ b/readme
@@ -0,0 +1,50 @@
+ Description
+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.
+Files with 'inner' part in their names are not intended for external use.
+Since filenames in the project are short and simple consider placing
+header files in subdirectory 'magi' of your include.
+
+ Compiling
+Compilation and its options are described in the 'Makefile'.
+Running 'make' produces 'libmagi.a' file, which is precompiled library itself,
+ready to be statically linked into your project.
+
+ Examples
+Compilation and its options are described in the local 'examples/Makefile'.
+Running 'make' in the 'examples' directory produces 'append', 'cookie',
+'upload', and 'echo' CGI executables. Descriptions and details are in
+corresponding source files.
+
+ Usage
+magi_request analyses incoming request, general workflow is to:
+1. Prepare request for analysis, setup defaults via 'magi_request_setup';
+2. Process non-post part of the CGI request via 'magi_request_cgi';
+ (The division of post and non-post analysis comes from the fact that
+ post body can be really huge, so you probably will want to specify
+ some constraints on it, based on non-post info. For example session id
+ from non-post part allowes some users (e.g. admins) to load more in post.)
+3. Process post part of the CGI request via 'magi_request_resume_cgi';
+4. Now you have the full request analysed, so do your work;
+5. And finally, free memory via 'magi_request_destroy'.
+For more see 'src/request.h'.
+
+magi_response provides output capabilities. You can form the response with
+'magi_response_setup' used to setup defaults, and the following functions to
+fill in your data ('...' means 'magi_response_'):
+ ...content_type: set Content Type (by default XHTML);
+ ...cookie: set HTTP Cookie;
+...cookie_discard: discard HTTP Cookie;
+ ...http: setup arbitarary HTTP header;
+ ...add: add something to the body;
+ ...add_format: add comething to the body, using format (similar to printf);
+Outputting itself can be done with 'magi_response_cgi'.
+To correctly free all occupied memory call 'magi_response_destroy'.
+For more see 'src/response.h'.
+
+ Motivation
+Web must be fun.
diff --git a/src/cgi.c b/src/cgi.c
index a0661dc..32b5b4d 100644
--- a/src/cgi.c
+++ b/src/cgi.c
@@ -3,12 +3,11 @@
#include "cookie.h"
#include "error.h"
#include "file.h"
-#include "inner_cookies.h"
-#include "inner_multipart.h"
#include "inner_tools.h"
-#include "inner_urlencoded.h"
+#include "multipart.h"
#include "param.h"
#include "request.h"
+#include "urlenc.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
@@ -169,9 +168,9 @@ static char * bound(const char * type)
type += strspn(type, " \t") + 1;
if (*type == '"') {
++type;
- res = magi_str_create_copy(type, strchr(type, '"'));
+ res = magi_str_create_copy(type, type - strchr(type, '"'));
} else {
- res = magi_str_create_copy(type, type + strcspn(type, " \t"));
+ res = magi_str_create_copy(type, strcspn(type, " \t"));
}
}
return res;
@@ -185,6 +184,8 @@ static int next(void * any)
/* Interfacial CGI Request Handling */
int magi_request_cgi(struct magi_request * request)
{
+ request->files = 0;
+ request->params = 0;
request->url_params = 0;
request->http_params = 0;
request->error = magi_error_none;
@@ -197,8 +198,6 @@ int magi_request_cgi(struct magi_request * request)
int magi_request_resume_cgi(struct magi_request * request)
{
enum magi_error * e = &request->error;
- request->files = 0;
- request->params = 0;
request->error = magi_error_none;
if (request->method && !strcmp(request->method, "post")) {
const char * t = getenv("CONTENT_TYPE");
@@ -264,9 +263,9 @@ void output_cookies(struct magi_cookie_list * list)
fputs("; Domain=", stdout);
fputs(list->item.domain, stdout);
}
- if (list->item.port) {
- fputs("; Port=", stdout);
- fputs(list->item.port, stdout);
+ if (list->item.max_age) {
+ fputs("; Max-Age=", stdout);
+ fputs(list->item.max_age, stdout);
}
fputs("\r\n", stdout);
list = list->next;
diff --git a/src/cookie.c b/src/cookie.c
index eaa221f..d1d82b3 100644
--- a/src/cookie.c
+++ b/src/cookie.c
@@ -16,16 +16,19 @@ int magi_cookie_list_add(struct magi_cookie_list ** list,
return !!node;
}
-struct magi_cookie * magi_cookie_list_get(struct magi_cookie_list * list,
- const char * name)
+char * magi_cookie_list_get(struct magi_cookie_list * list, const char * name)
{
+ char * res = 0;
if (!list || !name) {
return 0;
- } else if (!strcmp(list->item.name, name)) {
- return &list->item;
- } else {
- return magi_cookie_list_get(list->next, name);
}
+ while (list) {
+ if (!strcmp(list->item.name, name)) {
+ res = list->item.data;
+ }
+ list = list->next;
+ }
+ return res;
}
void magi_cookie_list_destroy(struct magi_cookie_list * list)
@@ -37,6 +40,6 @@ void magi_cookie_list_destroy(struct magi_cookie_list * list)
free(list->item.data);
free(list->item.path);
free(list->item.domain);
- free(list->item.port);
+ free(list->item.max_age);
}
}
diff --git a/src/inner_cookies.c b/src/inner_cookies.c
index d9035c4..9dfde7a 100644
--- a/src/inner_cookies.c
+++ b/src/inner_cookies.c
@@ -1,7 +1,7 @@
/* * * TODO * * */
#include "inner_cookies.h"
-#include "utils.h"
+#include "inner_tools.h"
#include <stdlib.h>
#include <string.h>
@@ -16,7 +16,7 @@ enum st {
st_post_data
};
-enum data_type { dt_plain = 0, dt_version, dt_path, dt_domain, dt_port };
+enum data_type { dt_plain = 0, dt_version, dt_path, dt_domain };
struct automata {
struct magi_cookie_list ** list;
@@ -25,7 +25,7 @@ struct automata {
int buf_len;
int buf_size;
int is_first;
- int is_cookie2;
+ int is_advanced;
int is_quoted;
enum data_type data_t;
};
@@ -33,11 +33,11 @@ struct automata {
static void nulify_cookie(struct automata * a)
{
- a->cookie.name = 0;
- a->cookie.data = 0;
- a->cookie.path = 0;
- a->cookie.domain = 0;
- a->cookie.port = 0;
+ a->cookie.name = 0;
+ a->cookie.data = 0;
+ a->cookie.path = 0;
+ a->cookie.domain = 0;
+ a->cookie.max_age = 0;
}
static void buf_new(struct automata * a)
@@ -53,13 +53,11 @@ static enum data_type what_is_name(const struct automata * a)
enum data_type data_t = dt_plain;
if (a->is_first && !strcmp(a->buf, "$Version")) {
data_t = dt_version;
- } else if (a->is_cookie2) {
+ } else if (a->is_advanced) {
if (!strcmp(a->buf, "$Path")) {
data_t = dt_path;
} else if (!strcmp(a->buf, "$Domain")) {
data_t = dt_domain;
- } else if (!strcmp(a->buf, "$Port")) {
- data_t = dt_port;
}
}
return data_t;
@@ -96,9 +94,6 @@ static int end_data(struct automata * a)
case dt_domain:
a->cookie.domain = a->buf;
break;
- case dt_port:
- a->cookie.port = a->buf;
- break;
case dt_version:
if (strcmp(a->buf, "1")) {
ok = 0;
@@ -291,6 +286,5 @@ void magi_cookies(struct magi_request * request, const char * data)
free(a.cookie.data);
free(a.cookie.path);
free(a.cookie.domain);
- free(a.cookie.port);
free(a.buf);
}
diff --git a/src/inner_multipart.c b/src/inner_multipart.c
index 65252e5..0187f7c 100644
--- a/src/inner_multipart.c
+++ b/src/inner_multipart.c
@@ -2,8 +2,8 @@
#include "inner_multipart.h"
#include "error.h"
+#include "inner_tools.h"
#include "param.h"
-#include "utils.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
@@ -74,9 +74,9 @@ static char * extract_filename(char * n)
n += strspn(n, " \t") + 1;
if (*n == '"') {
++n;
- return magi_str_create_copy(n, strchr(n, '"'));
+ return magi_str_create_copy(n, n - strchr(n, '"'));
} else {
- return magi_str_create_copy(n, n + strcspn(n, " \t"));
+ return magi_str_create_copy(n, strcspn(n, " \t"));
}
}
@@ -89,12 +89,12 @@ static int content_disposition(struct automata * a)
n += strspn(n, " \t") + 1;
if (*n == '"') {
++n;
- a->param.name = magi_str_create_copy(n, strchr(n, '"'));
+ a->param.name = magi_str_create_copy(n, n - strchr(n, '"'));
if (!a->param.name || !*a->param.name) {
return 0;
}
} else {
- a->param.name = magi_str_create_copy(n, n + strcspn(n, " \t"));
+ a->param.name = magi_str_create_copy(n, strcspn(n, " \t"));
if (!a->param.name || !is_str_token(a->param.name)) {
return 0;
}
diff --git a/src/inner_tools.c b/src/inner_tools.c
new file mode 100644
index 0000000..d958851
--- /dev/null
+++ b/src/inner_tools.c
@@ -0,0 +1,51 @@
+#include "inner_tools.h"
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+void magi_str_lowercase(char *str)
+{
+ if (!str) {
+ return;
+ }
+ for (; *str; ++str) {
+ *str = tolower(*str);
+ }
+}
+
+char *magi_str_create_copy(const char *first, int len)
+{
+ char *copy = magi_str_create(len);
+ if (copy) {
+ memcpy(copy, first, len);
+ }
+ return copy;
+}
+
+char *magi_str_create(int len)
+{
+ char *str = malloc(len + 1);
+ if (str) {
+ str[len] = 0;
+ }
+ return str;
+}
+
+int magi_str_add(char **dest, int *len, int *size, char c)
+{
+ if (!*dest) {
+ *dest = magi_str_create(1);
+ } else if (*len + 1 == *size) {
+ *size *= 2;
+ *dest = realloc(*dest, *size);
+ }
+ if (!*dest) {
+ return 0;
+ }
+ (*dest)[*len] = c;
+ ++*len;
+ (*dest)[*len] = 0;
+ return 1;
+}
diff --git a/src/inner_tools.h b/src/inner_tools.h
new file mode 100644
index 0000000..87489c8
--- /dev/null
+++ b/src/inner_tools.h
@@ -0,0 +1,19 @@
+#ifndef MAGI_INCLUDED_INNER_TOOLS
+#define MAGI_INCLUDED_INNER_TOOLS
+/* Magi Inner Tools
+ * This file must not be included in header files intended for external use,
+ * it contains some common utility functions for use in source files.
+ */
+
+
+void magi_str_lowercase(char *str);
+
+/* Results of both create functions are malloced, so need to be freed. */
+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);
+
+
+#endif
diff --git a/src/request.c b/src/request.c
index e905e53..8c3a101 100644
--- a/src/request.c
+++ b/src/request.c
@@ -21,73 +21,6 @@ void magi_request_setup(struct magi_request * request)
}
}
-void magi_tempfiles_add(struct magi_tempfiles * tmps,
- const char * name,
- const char * path,
- int max)
-{
- if (!tmps) {
- return;
- }
- if (tmps->count++) {
- tmps->param_names = realloc(tmps->param_names,
- sizeof(*tmps->param_names) * tmps->count);
- tmps->locations =
- realloc(tmps->locations, sizeof(*tmps->locations) * tmps->count);
- tmps->maximums =
- realloc(tmps->maximums, sizeof(*tmps->maximums) * tmps->count);
- } else {
- tmps->param_names = malloc(sizeof(*tmps->param_names));
- tmps->locations = malloc(sizeof(*tmps->locations));
- tmps->maximums = malloc(sizeof(*tmps->maximums));
- }
- tmps->param_names[tmps->count - 1] = name;
- tmps->locations[tmps->count - 1] = path;
- tmps->maximums[tmps->count - 1] = max;
-}
-
-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;
- for (pos = 0; pos != table->count; ++pos) {
- if (!strcmp(table->param_names[pos], file->param_name)) {
- static FILE * f = 0;
- static int unlimited;
- static int left;
- if (!f) {
- const char * loc = table->locations[pos];
- f = fopen(loc, "wb");
- left = table->maximums[pos];
- 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;
-}
-
static void request_free(struct magi_request * request)
{
@@ -147,3 +80,78 @@ 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/request.h b/src/request.h
index ffa239f..18d6c8e 100644
--- a/src/request.h
+++ b/src/request.h
@@ -113,8 +113,5 @@ void magi_tempfiles_destroy(magi_tempfiles *tmps);
void magi_request_setup_tempfiles(magi_request *request,
magi_tempfiles *table);
-/* Destroys request. */
-void magi_request_destroy(struct magi_request * request);
-
#endif
diff --git a/src/response.c b/src/response.c
index e4cd342..fdeba34 100644
--- a/src/response.c
+++ b/src/response.c
@@ -1,6 +1,6 @@
#include "response.h"
-#include "utils.h"
+#include "inner_tools.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@@ -23,6 +23,7 @@ void magi_response_setup(magi_response *response)
void magi_response_content_type(magi_response *response, const char *type)
{
+<<<<<<< HEAD
static const char *const ct = "Content-Type: ";
static const int ctlen = 15;
const int len = strlen(type);
@@ -30,6 +31,15 @@ void magi_response_content_type(magi_response *response, const char *type)
response->content_type = malloc(ctlen + len + 1);
memcpy(response->content_type, ct, ctlen);
memcpy(response->content_type + ctlen, type, len + 1);
+=======
+ const char * const messages[] = {
+ "Content-Type: application/xhtml+xml", /* magi_xhtml */
+ };
+ if (!response->content_type) {
+ response->content_type = magi_str_create_copy(messages[type],
+ strlen(messages[type]));
+ }
+>>>>>>> master
}
void magi_response_add(magi_response *r, const char *addon)
diff --git a/src/urlenc.c b/src/urlenc.c
index bb0bada..64a087e 100644
--- a/src/urlenc.c
+++ b/src/urlenc.c
@@ -1,6 +1,6 @@
#include "urlenc.h"
-#include "utils.h"
+#include "inner_tools.h"
#include <ctype.h>
#include <string.h>
diff --git a/src/utils.c b/src/utils.c
deleted file mode 100644
index 931d1e4..0000000
--- a/src/utils.c
+++ /dev/null
@@ -1,50 +0,0 @@
-#include "utils.h"
-
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-void magi_str_lowercase(char * str)
-{
- if (str) {
- while (*str) {
- *str = tolower(*str);
- ++str;
- }
- }
-}
-
-char * magi_str_create_copy(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;
-}
-
-char * magi_str_create(int len)
-{
- char * str = malloc(len + 1);
- if (str) {
- str[len] = 0;
- }
- return str;
-}
-
-int magi_str_add(char ** dest, int * len, int * size, char c)
-{
- if (*len + 1 == *size) {
- *size *= 2;
- *dest = realloc(*dest, *size);
- }
- if (*dest) {
- (*dest)[*len] = c;
- ++*len;
- (*dest)[*len] = 0;
- }
- return !!*dest;
-}
diff --git a/src/utils.h b/src/utils.h
deleted file mode 100644
index f67c66c..0000000
--- a/src/utils.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef MAGI_INCLUDED_UTILS
-#define MAGI_INCLUDED_UTILS
-
-
-void magi_str_lowercase(char * str);
-
-/* Results of both create functions are malloced, so need to be freed. */
-char * magi_str_create_copy(const char * begin, const char * end);
-char * magi_str_create(int len);
-
-/* Null only in case of error. */
-int magi_str_add(char ** dest, int * len, int * size, char c);
-
-
-#endif