timekeeper

My first (abandoned unfinished) web application for time tracking
git clone git://jacobedwards.org/timekeeper
Log | Files | Refs | README

page.c (3829B)


      1 #define const
      2 
      3 #include <sys/types.h>
      4 #include <stdarg.h>
      5 #include <stddef.h>
      6 #include <stdint.h>
      7 #include <kcgi.h>
      8 #include <kcgihtml.h>
      9 
     10 #include "user.h"
     11 #include "page.h"
     12 #include "key.h"
     13 
     14 enum kcgi_err
     15 loadpagerequest(struct kfcgi *fcgi, struct pagedata *pd)
     16 {
     17 	int status;
     18 
     19 	status = khttp_fcgi_parse(fcgi, &pd->req);
     20 	if (status != KCGI_OK)
     21 		return status;
     22 
     23 	pd->user = NULL;
     24         if (!pd->req.cookiemap[KeyHash])
     25                 return KCGI_OK;
     26 
     27 	status = getuser(&pd->user, pd, "token", pd->req.cookiemap[KeyHash]->parsed.s);
     28 	if (status == LoginValid || status == LoginNotFound)
     29 		return KCGI_OK;
     30 
     31 	khttp_free(&pd->req);
     32 	return KCGI_SYSTEM;
     33 }
     34 
     35 void
     36 freepagerequest(struct pagedata *pd)
     37 {
     38 	freeuser(pd->user);
     39 	khttp_free(&pd->req);
     40 }
     41 
     42 enum kcgi_err
     43 startpage(struct pagedata *pd, struct pagetemplate *t, enum khttp code)
     44 {
     45 	char **p;
     46 	enum kcgi_err status;
     47 
     48 	if ((status = khttp_head(&pd->req, kresps[KRESP_STATUS],
     49 	    "%s", khttps[code])) != KCGI_OK ||
     50 	    (status = khttp_head(&pd->req, kresps[KRESP_CONTENT_TYPE],
     51 	    "%s", kmimetypes[KMIME_TEXT_HTML])) != KCGI_OK ||
     52 	    (status = khttp_body(&pd->req)) != KCGI_OK)
     53 		return status;
     54 
     55 	if ((status = khtml_open(&pd->html, &pd->req, KHTML_PRETTY)) != KCGI_OK ||
     56 	    (status = khtml_elem(&pd->html, KELEM_DOCTYPE)) != KCGI_OK ||
     57 	    (status = khtml_elem(&pd->html, KELEM_HTML)) != KCGI_OK ||
     58 	    (status = khtml_elem(&pd->html, KELEM_HEAD)) != KCGI_OK ||
     59 	    (status = khtml_elem(&pd->html, KELEM_TITLE)) != KCGI_OK ||
     60 	    (status = khtml_puts(&pd->html, t->title ? t->title : "Untitled")) != KCGI_OK ||
     61 	    (status = khtml_closeelem(&pd->html, 1)) != KCGI_OK)
     62 		return status;
     63 
     64 	if (t->css) {
     65 		for (p = t->css; *p; ++p) {
     66 			if ((status = khtml_attr(&pd->html, KELEM_LINK,
     67 			    KATTR_HREF, *p, KATTR_REL, "stylesheet", KATTR__MAX)) != KCGI_OK ||
     68 			    (status = khtml_closeelem(&pd->html, 1)) != KCGI_OK)
     69 				return status;
     70 		}
     71 	}
     72 
     73 	if ((status = khtml_elem(&pd->html, KELEM_BODY)) != KCGI_OK)
     74 		return status;
     75 	pd->bodypos = khtml_elemat(&pd->html);
     76 	return KCGI_OK;
     77 }
     78 
     79 enum kcgi_err
     80 endpage(struct pagedata *pd, struct pagetemplate *t)
     81 {
     82 	char **p;
     83 	enum kcgi_err status;
     84 
     85 	khtml_closeto(&pd->html, pd->bodypos);
     86 	if (t->scripts) {
     87 		for (p = t->scripts; *p; ++p) {
     88 			if ((status = khtml_attr(&pd->html, KELEM_SCRIPT,
     89 			    KATTR_SRC, *p, KATTR__MAX)) != KCGI_OK ||
     90 			    (status = khtml_closeelem(&pd->html, 1)) != KCGI_OK)
     91 				return status;
     92 		}
     93 	}
     94 
     95 	return khtml_closeelem(&pd->html, -1);
     96 }
     97 
     98 enum kcgi_err
     99 errorpage(struct pagedata *pd, enum khttp code)
    100 {
    101         enum kcgi_err status;
    102 
    103 	kutil_warn(&pd->req, pd->user ? pd->user->name : NULL,
    104 	    "%s: %s", pd->req.fullpath, khttps[code]);
    105 
    106         if ((status = khttp_head(&pd->req, kresps[KRESP_STATUS],
    107 		"%s", khttps[code])) != KCGI_OK ||
    108             (status = khttp_head(&pd->req, kresps[KRESP_CONTENT_TYPE],
    109 		"%s", kmimetypes[KMIME_TEXT_HTML])) != KCGI_OK ||
    110             (status = khttp_body(&pd->req)))
    111                 return status;
    112         return khttp_printf(&pd->req,
    113             "<!DOCTYPE HTML><html><head><title>%1$s</title></head><h1>%1$s</h1></html>",
    114             khttps[code]);
    115 }
    116 
    117 enum kcgi_err
    118 showpage(struct pagedata *pd, char **names,
    119     enum kcgi_err (*functions[])(struct pagedata *), size_t len,
    120     enum kcgi_err (*errorpage)(struct pagedata *, enum khttp))
    121 {
    122 	enum kcgi_err status;
    123 	char *ident;
    124 
    125 	ident = pd->user ? pd->user->name : NULL;
    126 
    127 	if (pd->req.page == len) {
    128 		kutil_info(&pd->req, ident,
    129 		    "%s: Invalid page requested", pd->req.fullpath);
    130 		status = errorpage(pd, KHTTP_404);
    131 	} else {
    132 		kutil_info(&pd->req, ident,
    133 		    "%s: Serving CGI page", pd->pages[pd->req.page]);
    134 		status = functions[pd->req.page](pd);
    135 		if (status != KCGI_OK)
    136 			kutil_warn(&pd->req, ident, "%s: returned %d",
    137 			    names[pd->req.page], status);
    138 	}
    139 
    140 	return status;
    141 }