/* Copyright (C) 2020 C. McEnroe * * 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 . */ #include #include #include #include #include #include #include #include #include #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 ); enum kcgi_err htmlSearch( struct khtmlreq *html, const char *network, const char *context );