# HG changeset patch # User David Demelier # Date 1677014522 -3600 # Node ID 6792975da9a0bc841d6ff0aa05211512a123f70a # Parent 1a98bc0daa490baa133194d6e32a5e9bcf7798e0 pasterd: start removing themes diff -r 1a98bc0daa49 -r 6792975da9a0 .hgignore --- a/.hgignore Wed Feb 01 13:12:59 2023 +0100 +++ b/.hgignore Tue Feb 21 22:22:02 2023 +0100 @@ -1,18 +1,21 @@ # vim/emacs specific. +\.swo$ +\.swp$ +^cscope\.out$ ^tags$ ^tags.lock$ ^tags.temp$ -\.swp$ -\.swo$ # macOS specific. \.DS_Store$ # Temporary files. +^extern/bcc/bcc$ ^libpaster\.a$ ^libsqlite3\.a$ \.o$ \.d$ +^html/.*\.h$ # Manual pages. ^paster(\.1)?$ diff -r 1a98bc0daa49 -r 6792975da9a0 INSTALL.md --- a/INSTALL.md Wed Feb 01 13:12:59 2023 +0100 +++ b/INSTALL.md Tue Feb 21 22:22:02 2023 +0100 @@ -15,7 +15,7 @@ Quick install. - $ tar xvzf paster-x.y.z-tar.xz + $ tar -xf paster-x.y.z-tar.xz $ cd paster-x.y.z $ make # sudo make install diff -r 1a98bc0daa49 -r 6792975da9a0 Makefile --- a/Makefile Wed Feb 01 13:12:59 2023 +0100 +++ b/Makefile Tue Feb 21 22:22:02 2023 +0100 @@ -19,26 +19,27 @@ .POSIX: # User options. -CC= cc CFLAGS= -DNDEBUG -O3 # Installation paths. PREFIX= /usr/local -BINDIR= ${PREFIX}/bin -SHAREDIR= ${PREFIX}/share -MANDIR= ${PREFIX}/share/man -VARDIR= ${PREFIX}/var +BINDIR= $(PREFIX)/bin +SHAREDIR= $(PREFIX)/share +MANDIR= $(PREFIX)/share/man +VARDIR= $(PREFIX)/var -VERSION= 0.2.1 +VERSION= 0.3.0 CORE_SRCS= config.c \ database.c \ - http.c \ - log.c \ + fmt.c \ + fmt-paste.c \ fragment-duration.c \ fragment-language.c \ fragment-paste.c \ fragment.c \ + http.c \ + log.c \ page-download.c \ page-fork.c \ page-index.c \ @@ -49,12 +50,19 @@ page.c \ paste.c \ util.c -CORE_OBJS= ${CORE_SRCS:.c=.o} +CORE_OBJS= $(CORE_SRCS:.c=.o) CORE_LIB= libpaster.a +HTML_SRCS= html/footer.html \ + html/header.html \ + html/index.html \ + html/paste-table.html \ + html/paste.html +HTML_OBJS= $(HTML_SRCS:.html=.h) + TESTS_SRCS= tests/test-database.c -TESTS_OBJS= ${TESTS_SRCS:.c=.o} -TESTS= ${TESTS_SRCS:.c=} +TESTS_OBJS= $(TESTS_SRCS:.c=.o) +TESTS= $(TESTS_SRCS:.c=) SQLITE_FLAGS= -DSQLITE_THREADSAFE=0 \ -DSQLITE_OMIT_LOAD_EXTENSION \ @@ -65,69 +73,77 @@ KCGI_INCS= `pkg-config --cflags kcgi kcgi-html` KCGI_LIBS= `pkg-config --libs kcgi kcgi-html` -INCS= -I. -Iextern ${KCGI_INCS} -DEFS= -D_POSIX_C_SOURCE=200809L -DVARDIR=\"${VARDIR}\" -DSHAREDIR=\"${SHAREDIR}\" -LIBS= ${KCGI_LIBS} -SED= sed -e "s|@SHAREDIR@|${SHAREDIR}|" \ - -e "s|@VARDIR@|${VARDIR}|" +INCS= -I. -Iextern $(KCGI_INCS) +DEFS= -D_POSIX_C_SOURCE=200809L -DVARDIR=\"$(VARDIR)\" -DSHAREDIR=\"$(SHAREDIR)\" +LIBS= $(KCGI_LIBS) +SED= sed -e "s|@SHAREDIR@|$(SHAREDIR)|" \ + -e "s|@VARDIR@|$(VARDIR)|" +BCC= extern/bcc/bcc .SUFFIXES: -.SUFFIXES: .o .c .sh +.SUFFIXES: .o .c .h .sh .html all: pasterd pasterd-clean paster .c.o: - ${CC} ${INCS} ${DEFS} ${CFLAGS} -c $< -o $@ + $(CC) $(INCS) $(DEFS) $(CFLAGS) -c $< -o $@ .o: - ${CC} ${INCS} ${DEFS} ${CFLAGS} $< -o $@ ${CORE_LIB} ${SQLITE_LIB} ${LIBS} ${LDFLAGS} + $(CC) $(INCS) $(DEFS) $(CFLAGS) $< -o $@ $(CORE_LIB) $(SQLITE_LIB) $(LIBS) $(LDFLAGS) + +.html.h: + $(BCC) -cs0 $< html_${ $@ .sh: - ${SED} < $< > $@ + $(SED) < $< > $@ + +$(SQLITE_LIB): extern/sqlite3.c extern/sqlite3.h + $(CC) $(CFLAGS) $(SQLITE_FLAGS) -c extern/sqlite3.c -o extern/sqlite3.o + $(AR) -rc $@ extern/sqlite3.o -${SQLITE_LIB}: extern/sqlite3.c extern/sqlite3.h - ${CC} ${CFLAGS} ${SQLITE_FLAGS} -c extern/sqlite3.c -o extern/sqlite3.o - ${AR} -rc $@ extern/sqlite3.o +$(HTML_OBJS): $(BCC) -${CORE_LIB}: ${CORE_OBJS} - ${AR} -rc $@ ${CORE_OBJS} +$(CORE_OBJS): $(HTML_OBJS) + +$(CORE_LIB): $(CORE_OBJS) + $(AR) -rc $@ $(CORE_OBJS) paster: paster.sh cp paster.sh paster chmod +x paster -pasterd.o pasterd-clean.o: ${CORE_LIB} ${SQLITE_LIB} +pasterd: $(CORE_LIB) $(SQLITE_LIB) clean: - rm -f ${SQLITE_LIB} extern/sqlite3.o - rm -f ${CORE_LIB} ${CORE_OBJS} + rm -f $(SQLITE_LIB) extern/sqlite3.o + rm -f $(CORE_LIB) $(CORE_OBJS) rm -f paster pasterd-clean pasterd - rm -f test.db ${TESTS_OBJS} + rm -f test.db $(TESTS_OBJS) install-paster: - mkdir -p ${DESTDIR}${BINDIR} - mkdir -p ${DESTDIR}${MANDIR}/man1 - cp paster ${DESTDIR}${BINDIR} - chmod 755 ${DESTDIR}${BINDIR}/paster - ${SED} < paster.1 > ${DESTDIR}${MANDIR}/man1/paster.1 + mkdir -p $(DESTDIR)$(BINDIR) + mkdir -p $(DESTDIR)$(MANDIR)/man1 + cp paster $(DESTDIR)$(BINDIR) + chmod 755 $(DESTDIR)$(BINDIR)/paster + $(SED) < paster.1 > $(DESTDIR)$(MANDIR)/man1/paster.1 install-pasterd: - mkdir -p ${DESTDIR}${BINDIR} - mkdir -p ${DESTDIR}${MANDIR}/man5 - mkdir -p ${DESTDIR}${MANDIR}/man8 - cp pasterd ${DESTDIR}${BINDIR} - cp pasterd-clean ${DESTDIR}${BINDIR} - mkdir -p ${DESTDIR}${SHAREDIR}/paster - cp -R themes ${DESTDIR}${SHAREDIR}/paster - ${SED} < pasterd.8 > ${DESTDIR}${MANDIR}/man8/pasterd.8 - ${SED} < pasterd-clean.8 > ${DESTDIR}${MANDIR}/man8/pasterd-clean.8 - ${SED} < pasterd-themes.5 > ${DESTDIR}${MANDIR}/man5/pasterd-themes.5 + mkdir -p $(DESTDIR)$(BINDIR) + mkdir -p $(DESTDIR)$(MANDIR)/man5 + mkdir -p $(DESTDIR)$(MANDIR)/man8 + cp pasterd $(DESTDIR)$(BINDIR) + cp pasterd-clean $(DESTDIR)$(BINDIR) + mkdir -p $(DESTDIR)$(SHAREDIR)/paster + cp -R themes $(DESTDIR)$(SHAREDIR)/paster + $(SED) < pasterd.8 > $(DESTDIR)$(MANDIR)/man8/pasterd.8 + $(SED) < pasterd-clean.8 > $(DESTDIR)$(MANDIR)/man8/pasterd-clean.8 + $(SED) < pasterd-themes.5 > $(DESTDIR)$(MANDIR)/man5/pasterd-themes.5 install: install-pasterd install-paster -${TESTS_OBJS}: ${CORE_LIB} ${SQLITE_LIB} +$(TESTS_OBJS): $(CORE_LIB) $(SQLITE_LIB) -tests: ${TESTS} - for t in ${TESTS}; do $$t; done +tests: $(TESTS) + for t in $(TESTS); do $$t; done .PHONY: all clean tests diff -r 1a98bc0daa49 -r 6792975da9a0 extern/LICENSE.bcc.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extern/LICENSE.bcc.txt Tue Feb 21 22:22:02 2023 +0100 @@ -0,0 +1,16 @@ +bcc ISC LICENSE +=============== + +Copyright (c) 2020-2021 David Demelier + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff -r 1a98bc0daa49 -r 6792975da9a0 extern/VERSION.bcc.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extern/VERSION.bcc.txt Tue Feb 21 22:22:02 2023 +0100 @@ -0,0 +1,1 @@ +2.0.1 diff -r 1a98bc0daa49 -r 6792975da9a0 extern/bcc/bcc.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extern/bcc/bcc.c Tue Feb 21 22:22:02 2023 +0100 @@ -0,0 +1,164 @@ +/* + * bcc.c -- binary to C/C++ arrays converter + * + * Copyright (c) 2020-2021 David Demelier + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include + +static const char *charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_"; +static char findentchar = '\t'; +static int findent = 1, fconst, fnull, fstatic; + +noreturn static void +usage(void) +{ + fprintf(stderr, "usage: bcc [-0cs] [-I tab-indent] [-i space-indent] input variable\n"); + exit(1); +} + +noreturn static void +die(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + fputs("abort: ", stderr); + vfprintf(stderr, fmt, ap); + va_end(ap); + exit(1); +} + +static char * +mangle(char *variable) +{ + char *p; + size_t pos; + + /* Remove extension. */ + if ((p = strrchr(variable, '.'))) + *p = '\0'; + + /* Remove disallowed characters. */ + while ((pos = strspn(variable, charset)) != strlen(variable)) + variable[pos] = '_'; + + return variable; +} + +static void +indent(void) +{ + for (int i = 0; i < findent; ++i) + putchar(findentchar); +} + +static void +put(int ch) +{ + printf("0x%02hhx", (unsigned char)ch); +} + +static void +process(const char *input, const char *variable) +{ + FILE *fp; + int ch, col = 0; + + if (strcmp(input, "-") == 0) + fp = stdin; + else if (!(fp = fopen(input, "rb"))) + die("%s: %s\n", input, strerror(errno)); + + if (fstatic) + printf("static "); + if (fconst) + printf("const "); + + printf("unsigned char %s[] = {\n", variable); + + for (ch = fgetc(fp); ch != EOF; ) { + if (col == 0) + indent(); + + put(ch); + + if ((ch = fgetc(fp)) != EOF || fnull) + printf(",%s", col < 3 ? " " : ""); + + if (++col == 4) { + col = 0; + putchar('\n'); + } + + /* Add final '\0' if required. */ + if (ch == EOF && fnull) { + if (col++ == 0) + indent(); + + put(0); + } + } + + if (col != 0) + printf("\n"); + + puts("};"); + fclose(fp); +} + +int +main(int argc, char **argv) +{ + int ch; + + while ((ch = getopt(argc, argv, "0cI:i:s")) != -1) { + switch (ch) { + case '0': + fnull = 1; + break; + case 'c': + fconst = 1; + break; + case 'I': + findentchar = '\t'; + findent = atoi(optarg); + break; + case 'i': + findentchar = ' '; + findent = atoi(optarg); + break; + case 's': + fstatic = 1; + break; + default: + break; + } + } + + argc -= optind; + argv += optind; + + if (argc < 2) + usage(); + + process(argv[0], mangle(argv[1])); +} diff -r 1a98bc0daa49 -r 6792975da9a0 fmt-paste.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fmt-paste.c Tue Feb 21 22:22:02 2023 +0100 @@ -0,0 +1,140 @@ +/* + * fmt-paste.c -- page formatter for pastes + * + * Copyright (c) 2020-2023 David Demelier + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include + +#include +#include + +#include "fmt-paste.h" +#include "fmt.h" +#include "paste.h" +#include "util.h" + +#include "html/paste.h" +#include "html/paste-table.h" + +static void +print_id(struct kreq *req, struct khtmlreq *html, const void *data) +{ + (void)html; + + khttp_puts(req, ((const struct paste *)data)->id); +} + +static void +print_title(struct kreq *req, struct khtmlreq *html, const void *data) +{ + (void)req; + + khtml_puts(html, ((const struct paste *)data)->title); +} + +static void +print_author(struct kreq *req, struct khtmlreq *html, const void *data) +{ + (void)req; + + khtml_puts(html, ((const struct paste *)data)->author); +} + +static void +print_language(struct kreq *req, struct khtmlreq *html, const void *data) +{ + (void)html; + + khttp_puts(req, ((const struct paste *)data)->language); +} + +static void +print_date(struct kreq *req, struct khtmlreq *html, const void *data) +{ + (void)html; + + const struct paste *paste = data; + + khttp_puts(req, bstrftime("%c", localtime(&paste->timestamp))); +} + +static void +print_expiration(struct kreq *req, struct khtmlreq *html, const void *data) +{ + (void)html; + + const struct paste *paste = data; + + khttp_puts(req, ttl(paste->timestamp, paste->duration)); +} + +#include +static void +print_pastes(struct kreq *req, struct khtmlreq *html, const void *data) +{ + (void)html; + + fmt_pastes(req, data); +} + +/* + * Generate each column for the given paste. + */ +void +fmt_paste(struct kreq *req, const struct paste *paste) +{ + assert(req); + assert(paste); + + fmt(req, html_paste, paste, (const struct fmt_printer []) { + { "id", print_id }, + { "title", print_title }, + { "author", print_author }, + { "language", print_language }, + { "date", print_date }, + { "expiration", print_expiration }, + { NULL, NULL } + }); +} + +/* + * Generate each row from all pastes + */ +void +fmt_pastes(struct kreq *req, const struct fmt_paste_vec *vec) +{ + for (size_t i = 0; i < vec->pastesz; ++i) + fmt_paste(req, &vec->pastes[i]); +} + +/* + * Generate an HTML table with all pastes inside as long as there is a + * keyword. + */ +void +fmt_paste_table(struct kreq *req, const struct fmt_paste_vec *vec) +{ + assert(req); + assert(pastes); + + fmt(req, html_paste_table, vec, (const struct fmt_printer []) { + { "pastes", print_pastes }, + { NULL, NULL } + }); +} diff -r 1a98bc0daa49 -r 6792975da9a0 fmt-paste.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fmt-paste.h Tue Feb 21 22:22:02 2023 +0100 @@ -0,0 +1,41 @@ +/* + * fmt-paste.h -- page formatter for pastes + * + * Copyright (c) 2020-2023 David Demelier + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef PASTER_FMT_PASTE_H +#define PASTER_FMT_PASTE_H + +#include + +struct kreq; +struct paste; + +struct fmt_paste_vec { + const struct paste *pastes; + size_t pastesz; +}; + +void +fmt_paste(struct kreq *, const struct paste *); + +void +fmt_pastes(struct kreq *, const struct fmt_paste_vec *); + +void +fmt_paste_table(struct kreq *, const struct fmt_paste_vec *); + +#endif /* !PASTER_FMT_PASTE_H */ diff -r 1a98bc0daa49 -r 6792975da9a0 fmt.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fmt.c Tue Feb 21 22:22:02 2023 +0100 @@ -0,0 +1,108 @@ +/* + * fmt.c -- page formatter + * + * Copyright (c) 2020-2023 David Demelier + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "fmt.h" +#include "util.h" + +struct tpl { + struct kreq *req; + struct khtmlreq html; + const struct fmt_printer *printers; + const void *data; +}; + +static int +callback(size_t index, void *arg) +{ + struct tpl *tpl = arg; + + tpl->printers[index].printer(tpl->req, &tpl->html, tpl->data); + + return 1; +} + +static void +kt_init(struct ktemplate *kt, struct tpl *tpl) +{ + /* + * We need to create a list of strings to be set in kt->key from the + * printer list. + */ + size_t count = 0; + const char **list; + + while (tpl->printers[count].keyword) + count++; + + list = ecalloc(count, sizeof (char *)); + + for (size_t i = 0; i < count; ++i) + list[i] = tpl->printers[i].keyword; + + kt->key = list; + kt->keysz = count; + kt->arg = tpl; + kt->cb = callback; + + /* HTML printer. */ + if (khtml_open(&tpl->html, tpl->req, 0) != KCGI_OK) + errx(1, "khtml_open"); +} + +static inline void +kt_free(struct ktemplate *kt, struct tpl *tpl) +{ + free((const char **)kt->key); + khtml_close(&tpl->html); +} + +void +fmt(struct kreq *req, + const unsigned char *html, + const void *data, + const struct fmt_printer *printers) +{ + assert(req); + assert(html); + + const char *str = (const char *)html; + struct ktemplate kt; + struct tpl tpl = { + .req = req, + .printers = printers, + .data = data + }; + + if (printers) { + kt_init(&kt, &tpl); + khttp_template_buf(req, &kt, str, strlen(str)); + kt_free(&kt, &tpl); + } else + khttp_template_buf(req, NULL, str, strlen(str)); +} diff -r 1a98bc0daa49 -r 6792975da9a0 fmt.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fmt.h Tue Feb 21 22:22:02 2023 +0100 @@ -0,0 +1,34 @@ +/* + * fmt.h -- page formatter + * + * Copyright (c) 2020-2023 David Demelier + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef PASTER_FMT_H +#define PASTER_FMT_H + +struct kreq; +struct khtmlreq; +struct paste; + +struct fmt_printer { + const char *keyword; + void (*printer)(struct kreq *, struct khtmlreq *, const void *); +}; + +void +fmt(struct kreq *, const unsigned char *, const void *, const struct fmt_printer *); + +#endif /* !PASTER_FMT_H */ diff -r 1a98bc0daa49 -r 6792975da9a0 html/footer.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/html/footer.html Tue Feb 21 22:22:02 2023 +0100 @@ -0,0 +1,2 @@ + + diff -r 1a98bc0daa49 -r 6792975da9a0 html/header.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/html/header.html Tue Feb 21 22:22:02 2023 +0100 @@ -0,0 +1,9 @@ + + + + + + @@title@@ + + + diff -r 1a98bc0daa49 -r 6792975da9a0 html/index.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/html/index.html Tue Feb 21 22:22:02 2023 +0100 @@ -0,0 +1,3 @@ +

Recent pastes

+ +@@paste-table@@ diff -r 1a98bc0daa49 -r 6792975da9a0 html/paste-table.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/html/paste-table.html Tue Feb 21 22:22:02 2023 +0100 @@ -0,0 +1,14 @@ + + + + + + + + + + + +@@pastes@@ + +
NameAuthorLanguageDateExpires in
diff -r 1a98bc0daa49 -r 6792975da9a0 html/paste.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/html/paste.html Tue Feb 21 22:22:02 2023 +0100 @@ -0,0 +1,7 @@ + + @@title@@ + @@author@@ + @@language@@ + @@date@@ + @@expiration@@ + diff -r 1a98bc0daa49 -r 6792975da9a0 page-index.c --- a/page-index.c Wed Feb 01 13:12:59 2023 +0100 +++ b/page-index.c Tue Feb 21 22:22:02 2023 +0100 @@ -16,45 +16,25 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include #include -#include -#include - -#include #include "database.h" +#include "fmt-paste.h" +#include "fmt.h" #include "fragment-paste.h" #include "page-index.h" #include "page.h" #include "paste.h" #include "util.h" -struct template { - struct kreq *req; - const struct paste *pastes; - size_t pastesz; -}; +#include "html/index.h" -static const char *keywords[] = { - "pastes" -}; - -static int -template(size_t keyword, void *arg) +static void +print_paste_table(struct kreq *req, struct khtmlreq *html, const void *data) { - struct template *tp = arg; + (void)html; - switch (keyword) { - case 0: - for (size_t i = 0; i < tp->pastesz; ++i) - fragment_paste(tp->req, &tp->pastes[i]); - break; - default: - break; - } - - return 1; + fmt_paste_table(req, data); } static void @@ -65,30 +45,29 @@ if (!database_recents(pastes, &pastesz)) page(r, NULL, KHTTP_500, "pages/500.html", "500"); - else + else { page_index_render(r, pastes, pastesz); - for (size_t i = 0; i < pastesz; ++i) - paste_finish(&pastes[i]); + for (size_t i = 0; i < pastesz; ++i) + paste_finish(&pastes[i]); + } } void page_index_render(struct kreq *r, const struct paste *pastes, size_t pastesz) { - struct template data = { - .req = r, + assert(r); + assert(pastes); + + struct fmt_paste_vec vec = { .pastes = pastes, .pastesz = pastesz }; - struct ktemplate kt = { - .key = keywords, - .keysz = NELEM(keywords), - .arg = &data, - .cb = template - }; - - page(r, &kt, KHTTP_200, "pages/index.html", "Recent pastes"); + page2(r, KHTTP_200, "recent pastes", html_index, &vec, (const struct fmt_printer []) { + { "paste-table", print_paste_table }, + { NULL, NULL } + }); } void diff -r 1a98bc0daa49 -r 6792975da9a0 page.c --- a/page.c Wed Feb 01 13:12:59 2023 +0100 +++ b/page.c Tue Feb 21 22:22:02 2023 +0100 @@ -16,53 +16,62 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include +#include +#include +#include +#include + +#include +#include + +#include "fmt.h" #include "page.h" #include "util.h" -struct template { - struct kreq *req; - const char *title; -}; +#include "html/header.h" +#include "html/footer.h" -static const char * const keywords[] = { - "title" -}; - -static int -template(size_t keyword, void *arg) +static void +print_title(struct kreq *req, struct khtmlreq *html, const void *data) { - struct template *tp = arg; + (void)req; - switch (keyword) { - case 0: - khttp_printf(tp->req, "%s", tp->title); - break; - default: - break; - } - - return 1; + khtml_printf(html, "%s", (const char *)data); } void page(struct kreq *req, const struct ktemplate *tmpl, enum khttp status, const char *file, const char *title) { - struct template data = { - .req = req, - .title = title - }; - struct ktemplate kt = { - .key = keywords, - .keysz = NELEM(keywords), - .arg = &data, - .cb = template - }; - khttp_head(req, kresps[KRESP_CONTENT_TYPE], "%s", kmimetypes[KMIME_TEXT_HTML]); khttp_head(req, kresps[KRESP_STATUS], "%s", khttps[status]); khttp_body(req); - khttp_template(req, &kt, path("fragments/header.html")); - khttp_template(req, tmpl, path(file)); - khttp_template(req, NULL, path("fragments/footer.html")); + + fmt(req, html_header, title, (const struct fmt_printer []) { + { "title", print_title }, + { NULL, NULL } + }); + fmt(req, html_footer, NULL, NULL); khttp_free(req); } + +void +page2(struct kreq *req, + enum khttp status, + const char *title, + const unsigned char *html, + const void *data, + const struct fmt_printer *printers) +{ + khttp_head(req, kresps[KRESP_CONTENT_TYPE], "%s", kmimetypes[KMIME_TEXT_HTML]); + khttp_head(req, kresps[KRESP_STATUS], "%s", khttps[status]); + khttp_body(req); + + fmt(req, html_header, title, (const struct fmt_printer []) { + { "title", print_title }, + { NULL, NULL } + }); + fmt(req, html, data, printers); + fmt(req, html_footer, NULL, NULL); + khttp_free(req); +} diff -r 1a98bc0daa49 -r 6792975da9a0 page.h --- a/page.h Wed Feb 01 13:12:59 2023 +0100 +++ b/page.h Tue Feb 21 22:22:02 2023 +0100 @@ -24,7 +24,17 @@ #include #include +struct fmt_printer; + void page(struct kreq *, const struct ktemplate *, enum khttp, const char *, const char *); +void +page2(struct kreq *, + enum khttp, + const char *, + const unsigned char *, + const void *, + const struct fmt_printer *); + #endif /* !PASTER_PAGE_H */ diff -r 1a98bc0daa49 -r 6792975da9a0 util.c --- a/util.c Wed Feb 01 13:12:59 2023 +0100 +++ b/util.c Tue Feb 21 22:22:02 2023 +0100 @@ -238,6 +238,17 @@ return strcpy(ret, str); } +void * +ecalloc(size_t n, size_t w) +{ + void *ptr; + + if (!(ptr = calloc(n, w))) + die(strerror(errno)); + + return ptr; +} + const char * bprintf(const char *fmt, ...) { diff -r 1a98bc0daa49 -r 6792975da9a0 util.h --- a/util.h Wed Feb 01 13:12:59 2023 +0100 +++ b/util.h Tue Feb 21 22:22:02 2023 +0100 @@ -25,6 +25,7 @@ #define NELEM(x) (sizeof (x) / sizeof (x)[0]) struct tm; +struct kreq; extern const char *languages[]; extern const size_t languagesz; @@ -35,6 +36,9 @@ char * estrdup(const char *); +void * +ecalloc(size_t, size_t); + const char * bprintf(const char *, ...);