diff options
Diffstat (limited to 'scooper.c')
-rw-r--r-- | scooper.c | 66 |
1 files changed, 64 insertions, 2 deletions
diff --git a/scooper.c b/scooper.c index 17c0ebc..2c7b58a 100644 --- a/scooper.c +++ b/scooper.c @@ -38,6 +38,24 @@ enum { DatabaseVersion = 4 }; static sqlite3 *db; +static 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 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 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)); +} + static struct { sqlite3_stmt *networks; sqlite3_stmt *contexts; @@ -162,8 +180,52 @@ static enum kcgi_err networks(struct kreq *req) { return error || khtml_close(&html); } +static const char *ContextsQuery = SQL( + SELECT name + FROM contexts + WHERE network = :network AND coalesce(query = :query, true) + ORDER BY query, name; +); + +bool public = false; + static enum kcgi_err contexts(struct kreq *req) { - return KCGI_OK; + if (!req->fieldmap[Network]) return fail(req, KHTTP_404); + const char *network = req->fieldmap[Network]->parsed.s; + + struct khtmlreq html; + enum kcgi_err error = head(req, KHTTP_200, KMIME_TEXT_HTML) + || khttp_body(req) + || khtml_open(&html, req, KHTML_PRETTY) + || htmlHead(&html, network) + || khtml_elem(&html, KELEM_UL); + if (error) return error; + + dbBindText(stmt.contexts, ":network", network); + if (public) dbBindInt(stmt.contexts, ":query", false); + + int result; + while (SQLITE_ROW == (result = sqlite3_step(stmt.contexts))) { + const char *context = (const char *)sqlite3_column_text(stmt.contexts, 0); + char *href = khttp_urlpart( + NULL, NULL, Pages[Events], + Keys[Network].name, network, + Keys[Context].name, context, + NULL + ); + if (!href) err(EX_OSERR, "khttp_urlpart"); + + error = khtml_elem(&html, KELEM_LI) + || khtml_attr(&html, KELEM_A, KATTR_HREF, href, KATTR__MAX) + || khtml_puts(&html, context) + || khtml_closeelem(&html, 2); + free(href); + if (error) break; + } + if (result != SQLITE_DONE) errx(EX_SOFTWARE, "%s", sqlite3_errmsg(db)); + + sqlite3_reset(stmt.contexts); + return error || khtml_close(&html); } static enum kcgi_err events(struct kreq *req) { @@ -196,7 +258,6 @@ static void prepare(sqlite3_stmt **stmt, const char *query) { int main(int argc, char *argv[]) { bool fastCGI = false; - bool public = false; for (int opt; 0 < (opt = getopt(argc, argv, "fps:"));) { switch (opt) { @@ -228,6 +289,7 @@ int main(int argc, char *argv[]) { sqlite3_finalize(check); prepare(&stmt.networks, NetworksQuery); + prepare(&stmt.contexts, ContextsQuery); if (fastCGI) { struct kfcgi *fcgi; |