diff options
Diffstat (limited to 'server.h')
-rw-r--r-- | server.h | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/server.h b/server.h new file mode 100644 index 0000000..80eb5bb --- /dev/null +++ b/server.h @@ -0,0 +1,129 @@ +/* Copyright (C) 2020 C. McEnroe <june@causal.agency> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <err.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <sys/types.h> +#include <sysexits.h> + +#include <kcgi.h> +#include <kcgihtml.h> +#include <sqlite3.h> + +#if KCGI_VMAJOR == 0 && KCGI_VMINOR < 12 +#define khttp_urlpart(...) kutil_urlpart(NULL, __VA_ARGS__) +#endif + +#define SQL(...) #__VA_ARGS__ + +enum { DatabaseVersion = 4 }; + +extern sqlite3 *db; + +extern const char *NetworksQuery; +extern const char *ContextsQuery; +extern const char *EventsQuery; +extern const char *SearchQuery; + +extern struct Statements { + sqlite3_stmt *networks; + sqlite3_stmt *contexts; + sqlite3_stmt *events; + sqlite3_stmt *search; +} stmt; + +static inline void dbClose(void) { + if (stmt.networks) sqlite3_finalize(stmt.networks); + if (stmt.contexts) sqlite3_finalize(stmt.contexts); + if (stmt.events) sqlite3_finalize(stmt.events); + if (stmt.search) sqlite3_finalize(stmt.search); + sqlite3_close(db); +} + +static inline int dbParam(sqlite3_stmt *stmt, const char *param) { + int index = sqlite3_bind_parameter_index(stmt, param); + if (index) return index; + errx(EX_SOFTWARE, "no such parameter %s: %s", param, sqlite3_sql(stmt)); +} + +static inline void +dbBindInt(sqlite3_stmt *stmt, const char *param, sqlite3_int64 value) { + if (!sqlite3_bind_int64(stmt, dbParam(stmt, param), value)) return; + errx(EX_SOFTWARE, "sqlite3_bind_int64: %s", sqlite3_errmsg(db)); +} + +static inline void +dbBindText(sqlite3_stmt *stmt, const char *param, const char *value) { + if (!sqlite3_bind_text(stmt, dbParam(stmt, param), value, -1, NULL)) return; + errx(EX_SOFTWARE, "sqlite3_bind_text: %s", sqlite3_errmsg(db)); +} + +#define ENUM_PAGES \ + X(Networks, "networks") \ + X(Contexts, "contexts") \ + X(Events, "events") \ + X(Search, "search") + +enum { +#define X(page, path) page, + ENUM_PAGES +#undef X + PagesLen, +}; + +extern const char *Pages[PagesLen]; + +#define ENUM_KEYS \ + X(Network, "network", kvalid_stringne) \ + X(Context, "context", kvalid_stringne) \ + X(After, "after", kvalid_stringne) \ + X(Query, "query", kvalid_stringne) + +enum { +#define X(key, name, valid) key, + ENUM_KEYS +#undef X + KeysLen, +}; + +extern const struct kvalid Keys[KeysLen]; + +extern bool pagePublic; + +enum kcgi_err pageNetworks(struct kreq *req); +enum kcgi_err pageContexts(struct kreq *req); +enum kcgi_err pageEvents(struct kreq *req); +enum kcgi_err pageSearch(struct kreq *req); + +static inline enum kcgi_err +httpHead(struct kreq *req, enum khttp http, enum kmime mime) { + return khttp_head(req, kresps[KRESP_STATUS], "%s", khttps[http]) + || khttp_head(req, kresps[KRESP_CONTENT_TYPE], "%s", kmimetypes[mime]); +} + +static inline enum kcgi_err httpFail(struct kreq *req, enum khttp http) { + return httpHead(req, http, KMIME_TEXT_PLAIN) + || khttp_body(req) + || khttp_printf(req, "%s\n", khttps[http]); +} + +extern const char *htmlStylesheet; +enum kcgi_err htmlHead(struct khtmlreq *html, const char *title); +enum kcgi_err htmlNav( + struct khtmlreq *html, const char *network, const char *context +); |