diff options
Diffstat (limited to 'litterbox.c')
-rw-r--r-- | litterbox.c | 79 |
1 files changed, 53 insertions, 26 deletions
diff --git a/litterbox.c b/litterbox.c index c3bc46e..f33ed22 100644 --- a/litterbox.c +++ b/litterbox.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 C. McEnroe <june@causal.agency> +/* Copyright (C) 2019 June McEnroe <june@causal.agency> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -128,6 +128,7 @@ static int searchLimit = 10; static char *self; static char *network; static char *chanTypes; +static char *statusmsg; static char *prefixes; static char *prefixModes; static char *listModes; @@ -182,6 +183,8 @@ static void handleReplyISupport(struct Message *msg) { set(&network, msg->params[i]); } else if (!strcmp(key, "CHANTYPES")) { set(&chanTypes, msg->params[i]); + } else if (!strcmp(key, "STATUSMSG")) { + set(&statusmsg, msg->params[i]); } else if (!strcmp(key, "PREFIX")) { strsep(&msg->params[i], "("); char *modes = strsep(&msg->params[i], ")"); @@ -214,8 +217,10 @@ static void handleReplyMOTD(struct Message *msg) { char *line = msg->params[1]; if (!strncmp(line, "- ", 2)) line += 2; size_t len = strlen(line); - if (motd.len + len + 1 > motd.cap) { - motd.cap = (motd.cap ? motd.cap * 2 : len + 1); + size_t req = motd.len + len + 1; + if (req > motd.cap) { + if (!motd.cap) motd.cap = 1024; + while (req > motd.cap) motd.cap *= 2; motd.buf = realloc(motd.buf, motd.cap); if (!motd.buf) err(EX_OSERR, "realloc"); } @@ -285,7 +290,7 @@ static void querySearch(struct Message *msg) { WHERE contexts.network = :network AND coalesce(contexts.query = :query, true) AND search MATCH :search - ORDER BY time DESC, event DESC + ORDER BY search.rowid DESC LIMIT :limit ) SELECT * FROM results @@ -315,7 +320,10 @@ static void querySearch(struct Message *msg) { if (!message) message = ""; if (!strcmp(user, "*")) user = nick; - format("NOTICE %s :(%s) [%s] ", msg->nick, context, time); + format( + "NOTICE %s :\3%02d%s\3: [%s] ", + msg->nick, color(context), context, time + ); switch (type) { break; case Privmsg: format("\3%d<%s>\3 %s\r\n", color(user), nick, message); @@ -424,21 +432,32 @@ static void insertEvent( dbRun(stmt); } +static enum Type messageType(struct Message *msg) { + if (msg->cmd[0] == 'N') return Notice; + if (strncmp(msg->params[1], "\1ACTION", 7)) return Privmsg; + if (msg->params[1][7] == ' ') { + msg->params[1] += 8; + } else if (msg->params[1][7] == '\1') { + msg->params[1] += 7; + } else { + return Privmsg; + } + size_t len = strlen(msg->params[1]); + if (msg->params[1][len - 1] == '\1') { + msg->params[1][len - 1] = '\0'; + } + return Action; +} + static void handlePrivmsg(struct Message *msg) { require(msg, true, 2); bool query = true; const char *context = msg->params[0]; + if (statusmsg) context += strspn(context, statusmsg); if (strchr(chanTypes, context[0])) query = false; if (!strcmp(context, self)) context = msg->nick; - - enum Type type = (!strcmp(msg->cmd, "NOTICE") ? Notice : Privmsg); - char *message = msg->params[1]; - if (!strncmp(message, "\1ACTION ", 8)) { - message += 8; - message[strcspn(message, "\1")] = '\0'; - type = Action; - } + enum Type type = messageType(msg); bool selfMessage = !strcmp(msg->nick, msg->params[0]); if (query && searchQuery && type == Privmsg) { @@ -451,7 +470,7 @@ static void handlePrivmsg(struct Message *msg) { insertContext(context, query); insertName(msg); - insertEvent(msg, type, context, NULL, message); + insertEvent(msg, type, context, NULL, msg->params[1]); } static void insertTopic( @@ -733,8 +752,9 @@ static void handle(struct Message *msg) { } static void atExit(void) { - if (client) tls_close(client); + dbExec(SQL(PRAGMA optimize;)); dbClose(); + if (client) tls_close(client); } static void quit(int sig) { @@ -747,12 +767,13 @@ static void quit(int sig) { int main(int argc, char *argv[]) { bool init = false; bool migrate = false; - const char *path = NULL; + const char *dbPath = NULL; const char *backup = NULL; bool insecure = false; const char *cert = NULL; const char *priv = NULL; + const char *trust = NULL; const char *defaultNetwork = NULL; const char *nick = "litterbox"; @@ -776,6 +797,7 @@ int main(int argc, char *argv[]) { { .val = 'n', .name = "nick", required_argument }, { .val = 'p', .name = "port", required_argument }, { .val = 'q', .name = "private-query", no_argument }, + { .val = 't', .name = "trust", required_argument }, { .val = 'u', .name = "user", required_argument }, { .val = 'v', .name = "verbose", no_argument }, { .val = 'w', .name = "pass", required_argument }, @@ -795,7 +817,7 @@ int main(int argc, char *argv[]) { break; case 'U': scooperURL = optarg; break; case 'b': backup = optarg; break; case 'c': cert = optarg; - break; case 'd': path = optarg; + break; case 'd': dbPath = optarg; break; case 'h': host = optarg; break; case 'i': init = true; break; case 'j': join = optarg; @@ -805,6 +827,7 @@ int main(int argc, char *argv[]) { break; case 'n': nick = optarg; break; case 'p': port = optarg; break; case 'q': searchQuery = Private; + break; case 't': trust = optarg; break; case 'u': user = optarg; break; case 'v': verbose = true; break; case 'w': pass = optarg; @@ -819,7 +842,7 @@ int main(int argc, char *argv[]) { int flags = SQLITE_OPEN_READWRITE; if (init) flags |= SQLITE_OPEN_CREATE; - dbFind(path, flags); + dbFind(dbPath, flags); atexit(atExit); if (init) { @@ -847,21 +870,26 @@ int main(int argc, char *argv[]) { client = tls_client(); if (!client) errx(EX_SOFTWARE, "tls_client"); + int error; + char path[PATH_MAX]; struct tls_config *config = tls_config_new(); if (!config) errx(EX_SOFTWARE, "tls_config_new"); - int error = tls_config_set_ciphers(config, "compat"); - if (error) { - errx(EX_SOFTWARE, "tls_config_set_ciphers: %s", tls_config_error(config)); - } if (insecure) { tls_config_insecure_noverifycert(config); tls_config_insecure_noverifyname(config); } + if (trust) { + tls_config_insecure_noverifyname(config); + for (int i = 0; configPath(path, sizeof(path), trust, i); ++i) { + error = tls_config_set_ca_file(config, path); + if (!error) break; + } + if (error) errx(EX_NOINPUT, "%s: %s", trust, tls_config_error(config)); + } if (cert) { - const char *dirs = NULL; - while (NULL != (path = configPath(&dirs, cert))) { + for (int i = 0; configPath(path, sizeof(path), cert, i); ++i) { if (priv) { error = tls_config_set_cert_file(config, path); } else { @@ -872,8 +900,7 @@ int main(int argc, char *argv[]) { if (error) errx(EX_NOINPUT, "%s: %s", cert, tls_config_error(config)); } if (priv) { - const char *dirs = NULL; - while (NULL != (path = configPath(&dirs, priv))) { + for (int i = 0; configPath(path, sizeof(path), priv, i); ++i) { error = tls_config_set_key_file(config, path); if (!error) break; } |