diff options
Diffstat (limited to 'search.c')
-rw-r--r-- | search.c | 83 |
1 files changed, 82 insertions, 1 deletions
diff --git a/search.c b/search.c index c9a9044..767081b 100644 --- a/search.c +++ b/search.c @@ -21,6 +21,87 @@ #include "server.h" +const char *SearchQuery = SQL( + SELECT + events.event, + events.time, + contexts.network, + contexts.name, + events.type, + names.nick, + names.user, + names.host, + events.target, + highlight(search, 6, :highlight, :highlight) + FROM events + JOIN contexts USING (context) + JOIN names USING (name) + JOIN search ON search.rowid = events.event + WHERE coalesce(contexts.network = :network, true) + AND coalesce(contexts.name = :context, true) + AND coalesce(contexts.query = :query, true) + AND search MATCH :search + LIMIT :limit + OFFSET :offset; +); + enum kcgi_err pageSearch(struct kreq *req) { - return httpFail(req, KHTTP_501); + if (!req->fieldmap[Query]) { + return httpFail(req, KHTTP_400); + } + if (req->fieldmap[Context] && !req->fieldmap[Network]) { + return httpFail(req, KHTTP_400); + } + const char *query = req->fieldmap[Query]->parsed.s; + + int64_t offset = 0; + const char *network = NULL; + const char *context = NULL; + if (req->fieldmap[Offset]) offset = req->fieldmap[Offset]->parsed.i; + if (req->fieldmap[Network]) network = req->fieldmap[Network]->parsed.s; + if (req->fieldmap[Context]) context = req->fieldmap[Context]->parsed.s; + + enum kcgi_err error = httpHead(req, KHTTP_200, KMIME_TEXT_HTML); + if (req->method == KMETHOD_HEAD) return error; + + struct khtmlreq html; + error = error + || khttp_body(req) + || khtml_open(&html, req, KHTML_PRETTY) + || htmlHead(&html, query) + || htmlNav(&html, network, context) + || khtml_elem(&html, KELEM_TABLE); + if (error) return error; + + dbBindText(stmt.search, ":highlight", "\26"); + dbBindText(stmt.search, ":network", network); + dbBindText(stmt.search, ":context", context); + if (pagePublic) dbBindInt(stmt.search, ":query", false); + dbBindText(stmt.search, ":search", query); + dbBindInt(stmt.search, ":limit", pageLimit); + dbBindInt(stmt.search, ":offset", offset); + + int result; + while (SQLITE_ROW == (result = sqlite3_step(stmt.search))) { + struct Event event = { + .event = sqlite3_column_int64(stmt.search, 0), + .time = sqlite3_column_int64(stmt.search, 1), + .network = (const char *)sqlite3_column_text(stmt.search, 2), + .context = (const char *)sqlite3_column_text(stmt.search, 3), + .type = sqlite3_column_int(stmt.search, 4), + .nick = (const char *)sqlite3_column_text(stmt.search, 5), + .user = (const char *)sqlite3_column_text(stmt.search, 6), + .host = (const char *)sqlite3_column_text(stmt.search, 7), + .target = (const char *)sqlite3_column_text(stmt.search, 8), + .message = (const char *)sqlite3_column_text(stmt.search, 9), + }; + error = htmlEvent(&html, event); + if (error) break; + } + if (result != SQLITE_DONE) errx(EX_SOFTWARE, "%s", sqlite3_errmsg(db)); + sqlite3_reset(stmt.search); + + return error + || htmlFooter(&html) + || khtml_close(&html); } |