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 }