Mercurial > imgup
view page-new.c @ 36:575c90cafc7e default tip @
imgupd: use id as filename
author | David Demelier <markand@malikania.fr> |
---|---|
date | Thu, 16 Mar 2023 12:56:46 +0100 |
parents | 3e01d0147294 |
children |
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 <sys/types.h> #include <assert.h> #include <stdarg.h> #include <stdint.h> #include <string.h> #include <kcgi.h> #include "database.h" #include "fragment-duration.h" #include "image.h" #include "page-new.h" #include "page.h" #include "util.h" static const char *keywords[] = { "durations" }; static const struct { const char *title; long long int secs; } durations[] = { { "day", IMAGE_DURATION_DAY }, { "hour", IMAGE_DURATION_HOUR }, { "week", IMAGE_DURATION_WEEK }, { "month", IMAGE_DURATION_MONTH }, }; static int template(size_t keyword, void *arg) { struct kreq *r = arg; switch (keyword) { case 0: for (size_t i = 0; i < NELEM(durations); ++i) fragment_duration(r, durations[i].title); break; default: break; } return 1; } static long long int duration(const char *val) { for (size_t i = 0; i < NELEM(durations); ++i) if (strcmp(val, durations[i].title) == 0) return durations[i].secs; /* Default to month. */ return IMAGE_DURATION_MONTH; } static void get(struct kreq *r) { struct ktemplate kt = { .key = keywords, .keysz = NELEM(keywords), .cb = template, .arg = r }; page(r, &kt, KHTTP_200, "pages/new.html", "Upload image"); } static void post(struct kreq *r) { struct image image = { .author = estrdup("Anonymous"), .title = estrdup("Untitled"), .visible = true, .duration = IMAGE_DURATION_DAY }; int raw = 0; for (size_t i = 0; i < r->fieldsz; ++i) { const char *key = r->fields[i].key; const char *val = r->fields[i].val; if (strcmp(key, "title") == 0) replace(&image.title, val); else if (strcmp(key, "author") == 0) replace(&image.author, val); else if (strcmp(key, "duration") == 0) image.duration = duration(val); else if (strcmp(key, "filename") == 0) { if (r->fields[i].file) replace(&image.filename, r->fields[i].file); image.data = ememdup(r->fields[i].val, r->fields[i].valsz); image.datasz = r->fields[i].valsz; } else if (strcmp(key, "private") == 0) image.visible = strcmp(val, "on") != 0; else if (strcmp(key, "raw") == 0) raw = strcmp(val, "on") == 0; } /* TODO: image_isvalid should check for all stuff. */ if (!image.data || !image_isvalid(image.data, image.datasz)) page(r, NULL, KHTTP_400, "pages/400.html", "400"); else if (!database_insert(&image)) page(r, NULL, KHTTP_500, "pages/500.html", "500"); else { if (raw) { /* For CLI users (e.g. imgup) just print the location. */ khttp_head(r, kresps[KRESP_STATUS], "%s", khttps[KHTTP_201]); khttp_body(r); khttp_printf(r, "%s://%s/image/%s\n", r->scheme == KSCHEME_HTTP ? "http" : "https", r->host, image.id); khttp_free(r); } else { /* Otherwise, redirect to image details. */ khttp_head(r, kresps[KRESP_STATUS], "%s", khttps[KHTTP_302]); khttp_head(r, kresps[KRESP_LOCATION], "/image/%s", image.id); khttp_body(r); khttp_free(r); } } image_finish(&image); } void page_new(struct kreq *r) { assert(r); switch (r->method) { case KMETHOD_GET: get(r); break; case KMETHOD_POST: post(r); break; default: break; } }