aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjustanothercatgirl <sotov@twistea.su>2025-04-01 21:37:43 +0300
committerjustanothercatgirl <sotov@twistea.su>2025-04-01 21:54:17 +0300
commita81c5876f2058605cc5f15525591acde3ae16a80 (patch)
tree37edb55c4733288c9e58a0da960a6e3918a12279
parent08403b616f9dad83cb1204eec83ba1252e3eb129 (diff)
Integrated STE into html generation & cleaned up code
-rw-r--r--.gitignore5
-rw-r--r--Makefile25
-rw-r--r--README.md12
m---------c_headers0
-rw-r--r--compile_flags.txt1
-rw-r--r--config.env.default1
-rw-r--r--favicon.ico0
-rw-r--r--include/common.h2
-rw-r--r--jals.dbbin16384 -> 8192 bytes
-rw-r--r--src/endpoints.c80
-rw-r--r--src/main.c20
-rw-r--r--template/args.html.ste12
-rw-r--r--template/linkadd.html.ste11
-rw-r--r--www/form-test.html (renamed from www/form.html)0
-rw-r--r--www/index.html6
15 files changed, 110 insertions, 65 deletions
diff --git a/.gitignore b/.gitignore
index 81fcc4c..8df7494 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,8 @@ mime.h
test/
build/
*.inc
+*.db
+*.ico
+linkadd.html
+args.html
+config.env
diff --git a/Makefile b/Makefile
index 372caed..7a101dd 100644
--- a/Makefile
+++ b/Makefile
@@ -3,19 +3,30 @@
GPERF = gperf
CC = gcc
-CFLAGS += -Ic_headers/include -Iinclude -ggdb -Wall -Wextra -DDEFAULT_ENDPOINTS_PATH=\"./endpoints.so\"
BLDDIR ?= build
+CFLAGS += -Ic_headers/include -Iinclude -I$(BLDDIR) -ggdb -Wall -Wextra -DDEFAULT_ENDPOINTS_PATH=\"./endpoints.so\"
all: $(BLDDIR) endpoints.so main
-.PHONY: all clean $(BLDDIR)
+.PHONY: all clean run
$(BLDDIR):
mkdir -p $(BLDDIR)
+$(BLDDIR)/template:
+ mkdir -p $@
+
+$(BLDDIR)/ste: c_headers/ste/ste.c
+ $(CC) -o $@ $<
+
+
+$(BLDDIR)/template/%: template/%.ste $(BLDDIR)/ste $(BLDDIR)/template
+ $(BLDDIR)/ste -o $@ $<
+
# endpoints
-$(BLDDIR)/endpoints.o: src/endpoints.c $(BLDDIR)/rename.ld $(BLDDIR)
+$(BLDDIR)/endpoints.o: src/endpoints.c $(BLDDIR) \
+ $(BLDDIR)/template/args.html $(BLDDIR)/template/linkadd.html
# PIC here is important
$(CC) -fPIC -c $< $(CFLAGS) -o $@
@@ -47,4 +58,10 @@ main: $(BLDDIR)/main.o $(BLDDIR)/mime.o $(BLDDIR)/common.o
$(CC) $(CFLAGS) $^ -ldl -lmicrohttpd -lsqlite3 -o $@
clean:
- $(RM) $(BLDDIR)/* main endpoints.o endpoints.so rename.ld include/mime.h.inc
+ $(RM) --recursive $(BLDDIR)/template/* $(BLDDIR)/* main endpoints.o endpoints.so rename.ld include/mime.h.inc
+
+veryclean: clean
+ $(RM) jals.db
+
+run: main endpoints.so
+ env $(shell cat config.env) ./main
diff --git a/README.md b/README.md
index ca47fd4..dd4b35b 100644
--- a/README.md
+++ b/README.md
@@ -11,6 +11,7 @@ chroot environment, who knows.
# Features
* Will try to process URLs in this order:
+
0. Checks if API endpoint exists at that URL, and if it does, and executes it.
0. Checks if URL is a shortened link name, and if it is, redirects there.
0. Tries to send a file at the location pointed to by URL (relative to
@@ -18,6 +19,7 @@ chroot environment, who knows.
0. Tries to format file like this: `www/{URL}.html` and display the page \[e.g.
`/docs` -> `www/docs.html`\]
0. Returns 404
+
* \[In future\]: uses `inotify` to track changes in `endpoints.so` and reload it
* \[In future\]: `SIGUSR1` makes it reload `endpoints.so`
@@ -26,6 +28,7 @@ Pretty small. See [html docs page](www/docs.html).
# Build
## Requirements
+0. `make`
0. `gperf`
0. `cc`
0. linker that supports `.ld` scripts
@@ -36,8 +39,15 @@ all of the paths can be configured in [`Makefile`](Makefile)
## Steps
`make`
+# Run
+0. Copy `config.env.default` to `config.env`, change environment variables in
+there to match your needs
+0. `make run`, or `env $(cat config.env) ./main`, or `. config.env && ./main`,
+whichever fits your needs the most.
+
# License
-AGPL. Sorry fellas, gotta stay free (as in "freedom").
+AGPL. Sorry fellas, gotta stay free (as in "freedom"). Also,
+[sorry, google employees](https://opensource.google/documentation/reference/patching#forbidden)
# Contributing
[my email](mailto:sotov@twistea.su)
diff --git a/c_headers b/c_headers
-Subproject 08b786a6770c172f433e28b0eb1e893f4fbae40
+Subproject 588976a9a16eaa0f1b694587b459b2b264e5fe4
diff --git a/compile_flags.txt b/compile_flags.txt
index 5feac12..d8044a7 100644
--- a/compile_flags.txt
+++ b/compile_flags.txt
@@ -1,2 +1,3 @@
-Ic_headers/include
-Iinclude
+-Ibuild
diff --git a/config.env.default b/config.env.default
new file mode 100644
index 0000000..1af9713
--- /dev/null
+++ b/config.env.default
@@ -0,0 +1 @@
+HTTPHOSTNAME=http://localhost
diff --git a/favicon.ico b/favicon.ico
deleted file mode 100644
index e69de29..0000000
--- a/favicon.ico
+++ /dev/null
diff --git a/include/common.h b/include/common.h
index 539ba3a..81b4ca2 100644
--- a/include/common.h
+++ b/include/common.h
@@ -6,7 +6,7 @@
#include <fcntl.h>
#include <sys/stat.h>
-typedef struct MHD_Response*(*endpoint)(struct MHD_Connection*, int *status);
+typedef struct MHD_Response*(*endpoint)(const char *method, struct MHD_Connection*, int *status);
typedef char *(*query_func)(const char *path);
char *duplicate(const char *x);
diff --git a/jals.db b/jals.db
index fdd26d0..939d4bb 100644
--- a/jals.db
+++ b/jals.db
Binary files differ
diff --git a/src/endpoints.c b/src/endpoints.c
index 8d1c05f..d8efb0c 100644
--- a/src/endpoints.c
+++ b/src/endpoints.c
@@ -8,25 +8,30 @@
#include <microhttpd.h>
+#include "common.h"
+#include "sql.h"
#include <log.h>
#define CONTAINER_IMPLEMENTATION
#define JACSON_IMPLEMENTATION
#define JACSON_EXPORT_RSNPRINTF
#include <jacson.h>
-
-#include "common.h"
-#include "sql.h"
+#define STRINGBUILDER_IMPLEMENTATION
+#include <stringbuilder.h>
+
+#define OUT(arg) jac_sb_append_buf(&resp, arg)
+
+#define REQUIRE_METHOD(methodvar, methodstr, statusp) \
+do { \
+ if (strcmp((methodvar), (methodstr)) != 0) { \
+ *statusp = MHD_HTTP_METHOD_NOT_ALLOWED; \
+ return NULL; \
+ } \
+} while (0)
const char *const JSON_ERROR = "{\"error\":\"%s\"}";
const char *const HTML_ERROR = "<!DOCTYPE html><html><body>Error: %s</body></html>";
-const char *const INSUFFICIENT_ARGUMENTS = "insufficient arguments";
-const char *const INVALID_ARGUMENTS = "invalid arguments";
-const char *const OCCUPIED = "occupied";
-const char *const SERVER_ERRORMSG = "server error";
-const char *const UNKNOWN = "unknown";
-const char *const HTML_PROLOGUE = "<!DOCTYPE html><html><head><meta charset=\"utf-8\"></head><body>";
-const char *const HTML_EPILOGUE = "</html></body>";
+const char *HTTPHOSTNAME = "http://127.0.0.1";
struct global_args {
enum {
@@ -43,19 +48,6 @@ static const struct fmt_const fmts[] = {
[GA_FMT_HTML] = {HTML_ERROR,"text/html"}
};
-// string builder
-struct sb {
- char* str;
- size_t sz;
- size_t ln;
-};
-
-size_t sbprintf(struct sb* s, const char* fmt, ...) {
- va_list l;
- va_start(l, fmt);
- return s->ln += __jacson_vrsnprintf(&s->str, &s->sz, s->ln, fmt, l);
-}
-
struct global_args parse_global_args(struct MHD_Connection *connection) {
const char* key, *val;
struct global_args ret = { .format = GA_FMT_JSON };
@@ -71,56 +63,54 @@ struct MHD_Response *ENDP_(struct MHD_Connection* connection, int *status) {
}
enum MHD_Result arg_builder (void *cls, enum MHD_ValueKind kind, const char *key, const char *value) {
- struct sb *html = cls;
- html->ln += __jacson_rsnprintf(&html->str, &html->sz, html->ln, "<li><p style=\"font-style:monospace;\">%s: %s</p></li>", key, value);
+ jac_sb *html = cls;
+ jac_sb_snprintf(html, "<li><p style=\"font-style:monospace;\">%s: %s</p></li>", key, value ? value : "&lt;none&gt;");
return MHD_YES;
}
// path: /getargs
-struct MHD_Response *ENDP_getargs(struct MHD_Connection *connection, int *status) {
- struct sb html = {calloc(64, 1), 63, 0};
- html.ln += __jacson_rsnprintf(&html.str, &html.sz, html.ln,
- "<!DOCTYPE html><html><head><meta charset=\"utf-8\"></head><body><h3>List of arguments</h3><ol>");
- MHD_get_connection_values(connection, MHD_GET_ARGUMENT_KIND, &arg_builder, &html);
- html.ln += __jacson_rsnprintf(&html.str, &html.sz, html.ln, "</ol></body></html>");
- const char *val = MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "test");
- if (val) LDEBUGVF(stderr, "test = %s\n", val);
- LDEBUGVF(stderr, "test pointer = %p", val);
- return MHD_create_response_from_buffer(html.ln, html.str, MHD_RESPMEM_MUST_FREE);
+struct MHD_Response *ENDP_getargs(const char *method, struct MHD_Connection *connection, int *status) {
+ jac_sb resp = jac_sb_new(64);
+# include "template/args.html"
+ return MHD_create_response_from_buffer(resp.size, resp.data, MHD_RESPMEM_MUST_FREE);
}
// API, path: /api/linkadd
-struct MHD_Response *ENDP_api_linkadd(struct MHD_Connection *connection, int *status) {
+struct MHD_Response *ENDP_api_linkadd(const char *method, struct MHD_Connection *connection, int *status) {
+ REQUIRE_METHOD(method, "GET", status);
const char *url = NULL, *path = NULL;
char newurl[12] = {0}, *newurlp = newurl;
- struct sb resp = {malloc(64), 63, 0};
+ jac_sb resp = jac_sb_new(64);
struct global_args glob = parse_global_args(connection);
struct MHD_Response *response;
if ((url = MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "url")) == NULL || *url == '\0') {
*status = db_error_status(DBERROR_ARGS);
- sbprintf(&resp, fmts[glob.format].error, INSUFFICIENT_ARGUMENTS);
+ jac_sb_snprintf(&resp, fmts[glob.format].error, db_error(DBERROR_ARGS));
goto exit;
}
path = MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "try");
- if (*path == '\0') path = NULL;
+ if (path && *path == '\0') path = NULL;
enum dberror err;
if ((err = db_add_url(url, path, &newurlp)) != DBERROR_SUCCESS) {
LWARNVF("Database write failed with error %i. Sql error: %s", err, sqlite3_errmsg(state.db));
*status = db_error_status(err);
- sbprintf(&resp, fmts[glob.format].error, db_error(err));
+ jac_sb_snprintf(&resp, fmts[glob.format].error, db_error(err));
goto exit;
}
- if (glob.format == GA_FMT_JSON) sbprintf(&resp, "{\"url\":\"%s\"}", newurlp);
- else sbprintf(&resp, "%sYour URL: <a href=\"/%s\">/%s</a>%s", HTML_PROLOGUE, newurlp, newurlp, HTML_EPILOGUE);
+ if (glob.format == GA_FMT_JSON)
+ jac_sb_snprintf(&resp, "{\"url\":\"%s\"}", newurlp);
+ else if (glob.format == GA_FMT_HTML) {
+# include "template/linkadd.html"
+ }
exit:
- response = MHD_create_response_from_buffer(resp.ln, resp.str, MHD_RESPMEM_MUST_FREE);
+ response = MHD_create_response_from_buffer(resp.size, resp.data, MHD_RESPMEM_MUST_FREE);
MHD_add_response_header(response, "Content-Type", fmts[glob.format].content_type);
return response;
}
// API, path: /api/linkdel
-struct MHD_Response *ENDP_api_linkdel(struct MHD_Connection *connection, int *status) {
+struct MHD_Response *ENDP_api_linkdel(const char *method, struct MHD_Connection *connection, int *status) {
}
// API, path: /api/linkget
-struct MHD_Response *ENDP_api_linkget(struct MHD_Connection *connection, int *status) { }
+struct MHD_Response *ENDP_api_linkget(const char *method, struct MHD_Connection *connection, int *status) { }
diff --git a/src/main.c b/src/main.c
index 431a9a7..3283525 100644
--- a/src/main.c
+++ b/src/main.c
@@ -49,7 +49,7 @@ enum MHD_Result process_connection(void *cls, struct MHD_Connection *connection,
} else if (handler != NULL) {
/* endpoint access */
LINFOF("Accessed endpoint at url %s", url);
- res = handler(connection, &status);
+ res = handler(method, connection, &status);
} else if ((newurl = arg->query(url + 1)) != NULL) {
LINFOF("Redirect from %s to %s", url, newurl);
response = "<!DOCTYPE html><html><body>Recirecting...</body></html>";
@@ -118,15 +118,15 @@ int main(int argc, char *argv[]) {
const char *dlpath = DEFAULT_ENDPOINTS_PATH;
const char *dbpath = DEFAULT_DATABASE_PATH;
struct MHD_Daemon *daemon = init(&sig, dlpath, dbpath);
- /* while (reload_library == 0) { */
- /* sigsuspend(&sig); */
- /* if (reload_library == 1) { */
- /* reload_dylib(dlpath, dbpath); */
- /* reload_library = 0; */
- /* } */
- /* } */
- getchar();
- if (arg.destructor) arg.destructor();
+ while (reload_library == 0) {
+ sigsuspend(&sig);
+ if (reload_library == 1) {
+ reload_dylib(dlpath, dbpath);
+ reload_library = 0;
+ }
+ }
+ getchar(); /* to be replaced with fork later */
+ arg.destructor();
dlclose(arg.dylib);
MHD_stop_daemon(daemon);
return 0;
diff --git a/template/args.html.ste b/template/args.html.ste
new file mode 100644
index 0000000..965c06b
--- /dev/null
+++ b/template/args.html.ste
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ </head>
+ <body>
+ <h3> List of arguments </h3>
+ <ol>
+ %MHD_get_connection_values(connection, MHD_GET_ARGUMENT_KIND, &arg_builder, &resp);%
+ </ol>
+ </body>
+</html>
diff --git a/template/linkadd.html.ste b/template/linkadd.html.ste
new file mode 100644
index 0000000..7fe3db3
--- /dev/null
+++ b/template/linkadd.html.ste
@@ -0,0 +1,11 @@
+<!DOCTYPE html><html>
+ <head>
+ <meta charset="utf-8"/>
+ <style>*{margin:0;padding:0;text-align:center;}</style>
+ </head>
+ <body>
+ <p> Your URL:
+ <a href="/%OUT(newurlp);%">%OUT(HTTPHOSTNAME);%/%OUT(newurlp);%</a>
+ </p>
+ </body>
+</html>
diff --git a/www/form.html b/www/form-test.html
index 79eb7b1..79eb7b1 100644
--- a/www/form.html
+++ b/www/form-test.html
diff --git a/www/index.html b/www/index.html
index ed48fc5..973c32b 100644
--- a/www/index.html
+++ b/www/index.html
@@ -12,10 +12,9 @@
<title>JAC's link shortener</title>
</head>
<body>
- <div>
<h1>Just another link shortener</h1>
<p>Try it out!</p>
- <form action="/api/linkadd" target="result">
+ <form action="/api/linkadd" target="result" accept-charset="utf-8">
<div>
<label>URL:</label>
<input type="url"name="url"required/>
@@ -28,8 +27,7 @@
<input type="submit"value="Shorten URL!"/>
</form>
<h3>Result:</h3>
- <iframe name="result"scrolling="no"/>
- </div>
+ <iframe name="result"scrolling="no"></iframe>
<p> For API documentation, go to <a href="/docs">documentation page</a></p>
</body>
</html>