aboutsummaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi.dcr@tutanota.com>2023-07-11 01:20:39 +0200
committerXavier Del Campo Romero <xavi.dcr@tutanota.com>2023-07-11 01:49:12 +0200
commite79e955d93e24a192c9bf94181294d0797e9fded (patch)
tree5c3697710b6aa004bb7e3747f4c8ba98b37d662d /main.c
parent4236c7fc3a7c7ef9f79b045cfd99c6575b16f7b1 (diff)
downloadslcl-e79e955d93e24a192c9bf94181294d0797e9fded.tar.gz
Allow admins to define their own stylesheet
slcl used to provide a hardcoded stylesheet. However, it would be desirable for some admins to provide a custom stylesheet without having to rebuild the application. Now, slcl creates a default stylesheet, namely style.css, into the target directory, that can be later modified by admins. While this might contradict the suckless philosophy a bit, hopefully some admins might find this new feature useful.
Diffstat (limited to 'main.c')
-rw-r--r--main.c108
1 files changed, 106 insertions, 2 deletions
diff --git a/main.c b/main.c
index 2dee5f6..26cdadc 100644
--- a/main.c
+++ b/main.c
@@ -6,6 +6,7 @@
#include "hex.h"
#include "http.h"
#include "page.h"
+#include "style.h"
#include "wildcard_cmp.h"
#include <openssl/err.h>
#include <openssl/rand.h>
@@ -24,6 +25,8 @@
#include <stdlib.h>
#include <string.h>
+#define STYLE_PATH "style.css"
+
struct form
{
char *key, *value;
@@ -59,7 +62,32 @@ static int serve_index(const struct http_payload *const p,
static int serve_style(const struct http_payload *const p,
struct http_response *const r, void *const user)
{
- return page_style(r);
+ int ret = -1;
+ struct auth *const a = user;
+ const char *const dir = auth_dir(a);
+ struct dynstr d;
+
+ dynstr_init(&d);
+
+ if (!dir)
+ {
+ fprintf(stderr, "%s: auth_dir failed\n", __func__);
+ goto end;
+ }
+ else if (dynstr_append(&d, "%s/" STYLE_PATH, dir))
+ {
+ fprintf(stderr, "%s: dynstr_append failed\n", __func__);
+ goto end;
+ }
+ else if ((ret = page_style(r, d.str)))
+ {
+ fprintf(stderr, "%s: page_style failed\n", __func__);
+ goto end;
+ }
+
+end:
+ dynstr_free(&d);
+ return ret;
}
static char *alloc_form_data(const char *const s, const char **const end)
@@ -1796,6 +1824,81 @@ end:
return ret;
}
+static int dump_default_style(const char *const path)
+{
+ int ret = -1;
+ FILE *const f = fopen(path, "wb");
+
+ if (!f)
+ {
+ fprintf(stderr, "%s: fopen(3) %s: %s\n",
+ __func__, path, strerror(errno));
+ goto end;
+ }
+ else if (!fwrite(style_default, style_default_len, 1, f))
+ {
+ fprintf(stderr, "%s: fwrite(3): %s\n", __func__, strerror(errno));
+ goto end;
+ }
+
+ printf("Dumped default stylesheet into %s\n", path);
+ ret = 0;
+
+end:
+ if (f && fclose(f))
+ {
+ fprintf(stderr, "%s: fclose(3): %s\n", __func__, strerror(errno));
+ ret = -1;
+ }
+
+ return ret;
+}
+
+static int ensure_style(const char *const dir)
+{
+ int ret = -1;
+ struct dynstr d;
+ struct stat sb;
+
+ dynstr_init(&d);
+
+ if (dynstr_append(&d, "%s/" STYLE_PATH, dir))
+ {
+ fprintf(stderr, "%s: dynstr_append user failed\n", __func__);
+ goto end;
+ }
+ else if (stat(d.str, &sb))
+ {
+ switch (errno)
+ {
+ case ENOENT:
+ if (dump_default_style(d.str))
+ {
+ fprintf(stderr, "%s: dump_default_style failed\n",
+ __func__);
+ goto end;
+ }
+
+ break;
+
+ default:
+ fprintf(stderr, "%s: stat(2): %s\n", __func__, strerror(errno));
+ goto end;
+ }
+ }
+ else if (!S_ISREG(sb.st_mode))
+ {
+ fprintf(stderr, "%s: %s not a regular file\n", __func__, d.str);
+ return -1;
+ }
+
+ ret = 0;
+
+end:
+ dynstr_free(&d);
+ return ret;
+}
+
int main(int argc, char *argv[])
{
int ret = EXIT_FAILURE;
@@ -1806,6 +1909,7 @@ int main(int argc, char *argv[])
if (parse_args(argc, argv, &dir, &port, &tmpdir)
|| init_dirs(dir)
+ || ensure_style(dir)
|| !(a = auth_alloc(dir)))
goto end;
@@ -1819,7 +1923,7 @@ int main(int argc, char *argv[])
if (!(h = handler_alloc(&cfg))
|| handler_add(h, "/", HTTP_OP_GET, serve_index, a)
|| handler_add(h, "/index.html", HTTP_OP_GET, serve_index, a)
- || handler_add(h, "/style.css", HTTP_OP_GET, serve_style, NULL)
+ || handler_add(h, "/style.css", HTTP_OP_GET, serve_style, a)
|| handler_add(h, "/user/*", HTTP_OP_GET, getnode, a)
|| handler_add(h, "/login", HTTP_OP_POST, login, a)
|| handler_add(h, "/logout", HTTP_OP_POST, logout, a)