From 3ee9bd5e30fd7500eb9e7bed54fcfa5a152e75f4 Mon Sep 17 00:00:00 2001 From: Meutel Date: Sun, 18 Dec 2016 17:09:20 +0100 Subject: [PATCH] Pages skeleton --- db.c | 1 + main.c | 206 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 207 insertions(+) create mode 100644 main.c diff --git a/db.c b/db.c index 1c1977d..9489bbb 100644 --- a/db.c +++ b/db.c @@ -57,6 +57,7 @@ db_open(struct kreq *r, const char *file) attempt = 0; // TODO max attempt, return 0 again: + // TODO open readonly rc = sqlite3_open(file, &db); if (SQLITE_BUSY == rc) { db_sleep(attempt++); diff --git a/main.c b/main.c new file mode 100644 index 0000000..20adc4d --- /dev/null +++ b/main.c @@ -0,0 +1,206 @@ +/* $Id$ */ +/* + * Copyright (c) 2016 Kristaps Dzonsons + * + * Permission to use, copy, modify, and 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 + +#include "extern.h" + +/* + * Start with five pages. + * As you add more pages, you'll start by giving them an identifier key + * in this enum. + */ +enum page { + PAGE_INDEX, + PAGE_BOOKS, + PAGE_AUTHORS, + PAGE_SERIES, + PAGE__MAX +}; + +static const char *const pages[PAGE__MAX] = { + "index", /* PAGE_INDEX */ + "books", /* PAGE_BOOKS */ + "authors", /* PAGE_AUTHORS */ + "series", /* PAGE_SERIES */ +}; + +/* + * Fill out all HTTP secure headers. + * Use the existing document's MIME type. + */ +static void +http_alloc(struct kreq *r, enum khttp code) +{ + + khttp_head(r, kresps[KRESP_STATUS], + "%s", khttps[code]); + khttp_head(r, kresps[KRESP_CONTENT_TYPE], + "%s", kmimetypes[r->mime]); + khttp_head(r, "X-Content-Type-Options", "nosniff"); + khttp_head(r, "X-Frame-Options", "DENY"); + khttp_head(r, "X-XSS-Protection", "1; mode=block"); +} + +/* + * Fill out all headers with http_alloc() then start the HTTP document + * body (no more headers after this point!) + */ +static void +http_open(struct kreq *r, enum khttp code) +{ + + http_alloc(r, code); + khttp_body(r); +} + +static void +sendbooks(struct kreq *r) +{ + struct kjsonreq req; + + http_open(r, KHTTP_200); + kjson_open(&req, r); + kjson_obj_open(&req); + kjson_putstringp($req, "data", "books"); + kjson_obj_close(&req); + kjson_close(&req); +} + +static void +sendauthors(struct kreq *r) +{ + struct kjsonreq req; + + http_open(r, KHTTP_200); + kjson_open(&req, r); + kjson_obj_open(&req); + kjson_putstringp($req, "data", "authors"); + kjson_obj_close(&req); + kjson_close(&req); +} + +static void +sendseries(struct kreq *r) +{ + struct kjsonreq req; + + http_open(r, KHTTP_200); + kjson_open(&req, r); + kjson_obj_open(&req); + kjson_putstringp($req, "data", "series"); + kjson_obj_close(&req); + kjson_close(&req); +} + +static void +sendindex(struct kreq *r) +{ + struct kjsonreq req; + + http_open(r, KHTTP_200); + kjson_open(&req, r); + kjson_obj_open(&req); + kjson_putstringp($req, "data", "index"); + kjson_obj_close(&req); + kjson_close(&req); +} + +int +main(void) +{ + struct kreq r; + enum kcgi_err er; + struct user *u; + + /* Log into a separate logfile (not system log). */ + + kutil_openlog(LOGFILE); + + /* Actually parse HTTP document. */ + + er = khttp_parse(&r, keys, KEY__MAX, + pages, PAGE__MAX, PAGE_INDEX); + + if (KCGI_OK != er) { + fprintf(stderr, "HTTP parse error: %d\n", er); + return(EXIT_FAILURE); + } + +#ifdef __OpenBSD__ + if (-1 == pledge("stdio rpath cpath wpath flock fattr", NULL)) { + kutil_warn(&r, NULL, "pledge"); + khttp_free(&r); + return(EXIT_FAILURE); + } +#endif + + /* + * Front line of defence: make sure we're a proper method, make + * sure we're a page, make sure we're a JSON file. + */ + + if (KMETHOD_GET != r.method && + KMETHOD_POST != r.method) { + http_open(&r, KHTTP_405); + khttp_free(&r); + return(EXIT_SUCCESS); + } else if (PAGE__MAX == r.page || + KMIME_APP_JSON != r.mime) { + http_open(&r, KHTTP_404); + khttp_puts(&r, "Page not found."); + khttp_free(&r); + return(EXIT_SUCCESS); + } + + if ( ! db_open(&r, DATADIR "/" DATABASE)) { + http_open(&r, KHTTP_500); + json_emptydoc(&r); + khttp_free(&r); + return(EXIT_SUCCESS); + } + + switch (r.page) { + case (PAGE_INDEX): + sendindex(&r); + break; + case (PAGE_BOOKS): + sendbooks(&r); + break; + case (PAGE_AUTHORS): + sendauthors(&r); + break; + case (PAGE_SERIES): + sendseries(&r); + break; + default: + abort(); + } + + db_close(&r); + khttp_free(&r); + return(EXIT_SUCCESS); +}