Pages skeleton
This commit is contained in:
parent
8fac881482
commit
3ee9bd5e30
1
db.c
1
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++);
|
||||
|
206
main.c
Normal file
206
main.c
Normal file
@ -0,0 +1,206 @@
|
||||
/* $Id$ */
|
||||
/*
|
||||
* Copyright (c) 2016 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
* 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 <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <kcgi.h>
|
||||
#include <kcgijson.h>
|
||||
|
||||
#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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user