diff options
-rw-r--r-- | Makefile | 13 | ||||
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | browse.c | 76 | ||||
-rw-r--r-- | config.h | 7 | ||||
-rw-r--r-- | main.c | 4 | ||||
-rwxr-xr-x | template/browse_file.html | 1 | ||||
-rw-r--r-- | util.c | 43 | ||||
-rw-r--r-- | util.h | 12 |
8 files changed, 145 insertions, 13 deletions
@@ -30,15 +30,21 @@ CC=cc CFLAGS_DEPS != pkg-config --cflags kcgi kcgi-html LDFLAGS_DEPS != pkg-config --libs kcgi kcgi-html -CFLAGS=-g -W -Wall -Wextra -DLOG_INFO $(CFLAGS_DEPS) +CFLAGS=-O2 -DLOG_INFO $(CFLAGS_DEPS) LDFLAGS=-static $(LDFLAGS_DEPS) +.if make(debug) +CFLAGS+=-g -W -Wall -Wextra -DTEMPLATE_DIR='"template"' +.endif + +debug: main + all: main .c.o: $(CC) -o $@ -c $< $(CFLAGS) -main: url.o http.o download.o browse.o main.o +main: util.o url.o http.o download.o browse.o main.o $(CC) -o $@ $> $(LDFLAGS) env: env.o @@ -48,7 +54,8 @@ kcgienv: kcgienv.o $(CC) -o $@ $> $(LDFLAGS) install: - install -o www -g www -m 0500 main /var/www/cgi-bin/vault + install -D -o www -g www -m 0500 main /var/www/cgi-bin/vault + install -D -o www -g www -m 0440 template/browse_file.html /var/www/usr/share/vault/template/browse_file.html clean: rm -f *.o *.BAK main @@ -10,7 +10,7 @@ It should also compile and run on any POSIX OS with minor modifications, althoug ## Configure -The parameters and their documentation are in the `config.h` source file. You should read and adjust this file as needed before you build. +The parameters and their documentation are in the `config.h` source file. You should read and adjust this file as needed before you build. The default config assumes a chrooted web server and sets a data directory `/vault-data` (that is `/var/www/vault-data` outside of the chroot). ## Build & run @@ -43,6 +43,7 @@ #include "config.h" #include "http.h" #include "url.h" +#include "util.h" /* * list of files for current directory @@ -153,13 +154,56 @@ build_file_list(struct kreq * r, char *request_dir) return 0; } +const char *const template_keys[] = {"name", "url"}; + +/* + * data required in the template function + */ +struct template_data { + struct kreq *r; + struct file *f; +}; + +static int +template_callback(size_t index, void *arg) +{ + struct kreq *r; + struct template_data *data; + + if (arg == NULL) { + kutil_warn(NULL, NULL, "Invalid data for browse template"); + return 0; + } + data = arg; + r = data->r; + switch (index) { + case 0: + /* name */ + K_OK(khttp_puts(r, data->f->name), r); + break; + case 1: + /* url */ + K_OK(khttp_puts(r, data->f->url), r); + break; + default: + kutil_warnx(r, NULL, "Invalid key index for browse template: %zd", index); + return 0; + } + + return 1; +} + void browse(struct kreq * r) { - size_t url_len; + size_t url_len, template_buf_len; char current_dir[PATH_MAX]; + char template_path[PATH_MAX]; + char *template_buf; struct file *file; struct khtmlreq html; + struct ktemplate template; + struct template_data data; /* check that the requested URL can be safely processed */ if (!check_request_path(r->path)) @@ -175,6 +219,18 @@ browse(struct kreq * r) if (build_file_list(r, current_dir) < 0) http_exit(r, KHTTP_500, "browse: Unable to build file list"); + /* read template */ + template_path[0] = '\0'; + strlcat(template_path, TEMPLATE_DIR, PATH_MAX); + url_len = strlcat(template_path, "/browse_file.html", PATH_MAX); + if (url_len == 0 || url_len >= PATH_MAX) + http_exit(r, KHTTP_404, "browse: Unable to read template"); + + template_buf = NULL; + if (read_file(template_path, &template_buf, &template_buf_len) < 0 + || template_buf == NULL) + http_exit(r, KHTTP_500, "browse: Unable to read template"); + /* we have all the data we need, we can start to write output page */ http_open(r, KHTTP_200, r->mime); @@ -190,17 +246,23 @@ browse(struct kreq * r) K_OK(khtml_puts(&html, "/"), r); K_OK(khtml_closeelem(&html, 1), r); + /* print file list */ + template.key = template_keys; + template.keysz = 2; + template.cb = template_callback; + template.arg = &data; + data.r = r; + K_OK(khtml_elem(&html, KELEM_UL), r); SLIST_FOREACH(file, &list, files) { - K_OK(khtml_elem(&html, KELEM_LI), r); - K_OK(khtml_attr(&html, KELEM_A, KATTR_HREF, file->url, KATTR__MAX), - r); - K_OK(khtml_puts(&html, file->name), r); - K_OK(khtml_closeelem(&html, 2), r); + data.f = file; + K_OK(khttp_template_buf(r, &template, template_buf, + template_buf_len), r); } K_OK(khtml_close(&html), r); - /* free list */ + /* free list template and list */ + free(template_buf); file = NULL; while (!SLIST_EMPTY(&list)) { file = SLIST_FIRST(&list); @@ -37,7 +37,7 @@ * files. */ #ifndef DATA_DIR -#define DATA_DIR "/var/www/vault-data" +#define DATA_DIR "/vault-data" #endif /* @@ -48,4 +48,9 @@ #define LOG_FILE "/var/log/vault.log" #endif +/* The directory that contains the HTML template files */ +#ifndef TEMPLATE_DIR +#define TEMPLATE_DIR "/usr/share/vault/template" +#endif + #endif /* CONFIG_H */ @@ -65,7 +65,9 @@ main(void) kcgi_strerror(parse_err)); /* A bit of security cannot hurt */ - if (-1 == unveil(DATA_DIR, "r") || -1 == unveil(NULL, NULL)) + if (-1 == unveil(DATA_DIR, "r") + || -1 == unveil(TEMPLATE_DIR, "r") + || -1 == unveil(NULL, NULL)) http_exit(&r, KHTTP_500, "Unveil failed: %s", strerror(errno)); if (-1 == pledge("stdio rpath wpath cpath", NULL)) http_exit(&r, KHTTP_500, "Pledge failed: %s", strerror(errno)); diff --git a/template/browse_file.html b/template/browse_file.html new file mode 100755 index 0000000..48834dc --- /dev/null +++ b/template/browse_file.html @@ -0,0 +1 @@ +<li><a href="@@url@@">@@name@@</a></li> @@ -0,0 +1,43 @@ +#include <stdio.h> +#include <stdlib.h> + +#include "util.h" + +int +read_file(char *path, char **output, size_t * read_size) +{ + long file_size; + FILE *fp; + + fp = fopen(path, "r"); + if (fp == NULL) + return -1; + + /* get file size */ + if (fseek(fp, 0L, SEEK_END) != 0) + return -1; + + file_size = ftell(fp); + if (file_size < 0) + return -1; + + /* rewind to file start */ + if (fseek(fp, 0L, SEEK_SET) != 0) + return -1; + + /* create output buffer */ + *output = malloc(sizeof(char) * (file_size + 1)); + if (*output == NULL) + return -1; + + /* read the file */ + *read_size = fread(*output, sizeof(char), file_size, fp); + if (*read_size == 0 || ferror(fp) != 0) { + free(*output); + return -1; + } + /* enforce string termination */ + (*output)[*read_size] = '\0'; + + return 0; +} @@ -0,0 +1,12 @@ +#ifndef UTIL_H +#define UTIL_H + +/* + * Reads the file denoted by path into a newly allocated output buffer. Returns + * 0 for success, -1 for error. read_size is the size of output buffer (only to + * be used in case of success). + */ +int + read_file(char *path, char **output, size_t * read_size); + +#endif /* UTIL_H */ |