Mercurial > paster
view page-new.c @ 81:1ffe2f5a8500
pasterd: use HTML files to allow themes
author | David Demelier <markand@malikania.fr> |
---|---|
date | Fri, 17 Mar 2023 07:56:01 +0100 |
parents | 52029a52a385 |
children | 0a29424e4486 |
line wrap: on
line source
/* * page-new.c -- page /new * * Copyright (c) 2020-2023 David Demelier <markand@malikania.fr> * * 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 <assert.h> #include <string.h> #include <stdlib.h> #include "database.h" #include "page-new.h" #include "page-status.h" #include "page.h" #include "paste.h" #include "util.h" #define TITLE "paster -- create a new paste" enum { KEYWORD_TITLE, KEYWORD_AUTHOR, KEYWORD_LANGUAGES, KEYWORD_DURATIONS, KEYWORD_CODE }; struct page { struct kreq *req; struct ktemplate template; const struct paste *paste; }; static const char * const keywords[] = { [KEYWORD_TITLE] = "title", [KEYWORD_AUTHOR] = "author", [KEYWORD_LANGUAGES] = "languages", [KEYWORD_DURATIONS] = "durations", [KEYWORD_CODE] = "code" }; static long long int duration(const char *val) { for (size_t i = 0; i < durationsz; ++i) if (strcmp(val, durations[i].title) == 0) return durations[i].secs; /* Default to day. */ return 60 * 60 * 24; } static int format(size_t kw, void *data) { struct page *page = data; struct khtmlreq html; khtml_open(&html, page->req, KHTML_PRETTY); switch (kw) { case KEYWORD_TITLE: if (page->paste) khtml_printf(&html, page->paste->title); break; case KEYWORD_AUTHOR: if (page->paste) khtml_printf(&html, page->paste->author); break; case KEYWORD_LANGUAGES: for (size_t i = 0; i < languagesz; ++i) { if (page->paste && strcmp(page->paste->language, languages[i]) == 0) khtml_attr(&html, KELEM_OPTION, KATTR_VALUE, languages[i], KATTR_SELECTED, "selected", KATTR__MAX ); else khtml_attr(&html, KELEM_OPTION, KATTR_VALUE, languages[i], KATTR__MAX); khtml_printf(&html, "%s", languages[i]); khtml_closeelem(&html, 1); } break; case KEYWORD_DURATIONS: for (size_t i = 0; i < durationsz; ++i) { khtml_attr(&html, KELEM_OPTION, KATTR_VALUE, durations[i].title, KATTR__MAX); khtml_printf(&html, "%s", durations[i].title); khtml_closeelem(&html, 1); } break; case KEYWORD_CODE: if (page->paste) khtml_puts(&html, page->paste->code); break; default: break; } khtml_close(&html); return 1; } static void get(struct kreq *r) { page_new_render(r, NULL); } static void post(struct kreq *req) { struct paste paste; const char *key, *val, *scheme; int raw = 0; paste_init(&paste); // TODO: add verification support. for (size_t i = 0; i < req->fieldsz; ++i) { key = req->fields[i].key; val = req->fields[i].val; if (strcmp(key, "title") == 0 && strlen(val)) replace(&paste.title, val); else if (strcmp(key, "author") == 0 && strlen(val)) replace(&paste.author, val); else if (strcmp(key, "language") == 0) replace(&paste.language, val); else if (strcmp(key, "duration") == 0) paste.duration = duration(val); else if (strcmp(key, "code") == 0) replace(&paste.code, val); else if (strcmp(key, "visible") == 0) paste.visible = strcmp(val, "on") == 0; else if (strcmp(key, "raw") == 0) raw = strcmp(val, "on") == 0; } if (database_insert(&paste) < 0) page_status(req, KHTTP_500); else { scheme = req->scheme == KSCHEME_HTTP ? "http" : "https"; if (raw) { /* For CLI users (e.g. paster) just print the location. */ khttp_head(req, kresps[KRESP_STATUS], "%s", khttps[KHTTP_201]); khttp_body(req); khttp_printf(req, "%s://%s/paste/%s\n", scheme, req->host, paste.id); } else { /* Otherwise, redirect to paste details. */ khttp_head(req, kresps[KRESP_STATUS], "%s", khttps[KHTTP_302]); khttp_head(req, kresps[KRESP_LOCATION], "/paste/%s", paste.id); khttp_body(req); } khttp_free(req); } paste_finish(&paste); } void page_new_render(struct kreq *req, const struct paste *paste) { assert(req); struct page self = { .req = req, .template = { .cb = format, .arg = &self, .key = keywords, .keysz = NELEM(keywords) }, .paste = paste }; page(req, KHTTP_200, TITLE, "new.html", &self.template); } void page_new(struct kreq *req) { assert(req); switch (req->method) { case KMETHOD_GET: get(req); break; case KMETHOD_POST: post(req); break; default: break; } }