# HG changeset patch # User David Demelier # Date 1613497042 -3600 # Node ID 3ea3361f0fc7944f9bee9a6012e1ecebce4957dc # Parent bbb3d3075ec27fdc6165bda574fce40691edf547 irccd: now track modes diff -r bbb3d3075ec2 -r 3ea3361f0fc7 .clang diff -r bbb3d3075ec2 -r 3ea3361f0fc7 .clang-format diff -r bbb3d3075ec2 -r 3ea3361f0fc7 .clang-tidy diff -r bbb3d3075ec2 -r 3ea3361f0fc7 .editorconfig diff -r bbb3d3075ec2 -r 3ea3361f0fc7 .hgignore diff -r bbb3d3075ec2 -r 3ea3361f0fc7 .hgsigs diff -r bbb3d3075ec2 -r 3ea3361f0fc7 .hgtags diff -r bbb3d3075ec2 -r 3ea3361f0fc7 CHANGES.md --- a/CHANGES.md Sun Feb 14 10:11:03 2021 +0100 +++ b/CHANGES.md Tue Feb 16 18:37:22 2021 +0100 @@ -2,68 +2,72 @@ ========================= irccd 4.0.0 ????-??-?? ----------------------- +====================== This is a major release. See MIGRATING.md file for more information. The biggest change is the rewrite from C++ to C. The only runtime dependency required is OpenSSL (if built with SSL support). -irccd: +irccd +----- - Irccd keeps track of nicknames in channels by capturing join/part/kick and mode changes. It is now more convenient from the plugins to quickly inspect if someone is present on a channel. -irccdctl: +irccdctl +-------- - Commands `plugin-reload` and `plugin-unload` can be invoked without arguments. - New `plugin-template` and `plugin-path` command which are synonyms of `plugin-config` but for templates and paths respectively. -plugins: +plugins +------- - tictactoe: now has a timeout in case of inactivity. -misc: +misc +---- - Split irccd-api manual page into individual irccd-api- for a better readability. - New `irccd.conf` and `irccdctl.conf` syntax. -network API: +network API +----------- - Network protocol uses plain text again. - Transport uses clear UNIX sockets only without passwords. -javascript API: +javascript API +-------------- - Brand new Irccd.Rule API to inspect and manage rules. - Brand new Irccd.Hook API to inspect and manage hooks. irccd 3.1.1 2021-01-04 ----------------------- +====================== - Synchronize `ping-timeout` option in `[server]` to 1800 seconds by default, - Enable `auto-reconnect` option in `[server]` by default as specified in the manual page. irccd 3.1.0 2020-07-03 ----------------------- - -irccd: +====================== - Added a new hook system. Hooks consist of an alternative approach to plugins to extend irccd in any language (#2342). irccd 3.0.3 2019-10-06 ----------------------- +====================== - Fix errors in irccdctl.conf example file (#2398), - Add example of password in irccdctl.conf and irccd.conf (#2407). irccd 3.0.2 2019-09-22 ----------------------- +====================== - Added *IRCCD_WITH_JS* CMake variable in irccd package (#2340), - Fixed trailing CTCP escape code (#2339), @@ -72,18 +76,19 @@ - Fixed invalid system configuration directory (#2263). irccd 3.0.1 2019-09-01 ----------------------- +====================== - Fixed an invalid template escape sequence (#2250), - Updated the default configuration files (#2249), - Fix RPATH handling for private libraries like Duktape (#2257). irccd 3.0.0 2019-08-15 ----------------------- +====================== This is a major release. See MIGRATING.md file for more information. -irccd: +irccd +----- - New sections `[paths]` and `[paths.plugin]` have been added to control standard paths for both irccd and plugins (#611), @@ -96,51 +101,59 @@ - Section `[format]` is renamed to `[templates]` (#1671), - New commands are available as irccd arguments `info` and `version` (#1672). -irccdctl: +irccdctl +-------- - New option `ipv4` in `[connect]` (#945), - New option `-o` in `rule-add` (#947), - New option `-o` and `-O` in `rule-edit` (#947). -irccd-test: +irccd-test +---------- - A brand new `irccd-test` program has been added to tests plugins on the command line (#569). -cmake: +cmake +----- - CMake no longer create a fake installation directory while building (#674), - All targets are placed into the `bin` directory while building (#715). -network API: +network API +----------- - Network commands return an error code instead of a string (#739). -javascript API: +javascript API +-------------- - The Irccd.Timer API now runs on top of Boost.Asio and no longer have custom buggy code (#595), - New Irccd.Server.isSelf function (#735). -internal: +internal +-------- - The code is now based on Boost for many internal parts of the core, (#593), (#594), (#595), (#681), (#697), - The libircclient has been replaced by a simple homemade library (#581). -misc: +misc +---- - The documentation is in pure manual pages now (#1674), - All command line options are now in short form only (#1673). -plugins: +plugins +------- - Introduce brand new joke plugin (#609), - Introduce brand new tictactoe plugin (#393), - Introduce brand new links plugin (#872). irccd 2.2.0 2017-09-26 ----------------------- +====================== - Add new Irccd.Util.cut function (#635), - Add new irccdctl commands to edit rules (#641), @@ -149,14 +162,14 @@ - Fix identity.ctcp-version option (#690). irccd 2.1.3 2017-07-28 ----------------------- +====================== - Rules are now case insensitive (#645), - Plugin hangman, history and logger are now case insensitive (#642), - Plugin hangman: fix successive word selection (#644). irccd 2.1.2 2017-06-02 ----------------------- +====================== - Fix SSL initialization error in libircclient (#653), - Fix various SSL warnings (#652), @@ -164,50 +177,57 @@ - Fix case sensitivity in hangman and roulette (#642). irccd 2.1.1 2017-03-07 ----------------------- +====================== - Fix invalid documented option transport.family, - Fix error when logs.type is set to console, - Fix invalid IPV6\_V6ONLY option in transports. irccd 2.1.0 2017-02-01 ----------------------- +====================== -irccd: +irccd +----- - Add SSL support in transports, - Add authentication support in transports, - Fix a warning about daemon on macOS. -javascript API: +javascript API +-------------- - New Irccd.File.lines function, - Various improvements in Irccd.File API. -plugins: +plugins +------- - Add new format section for plugins, - Add unit tests for plugins. -irccdctl: +irccdctl +-------- - Added brand new plugin-config command, - Added aliases, - Added unit tests for irccdctl commands. -libraries: +libraries +--------- - Replaced jansson with Niels Lohmann's JSON library, - Updated Duktape to 1.5.1. -misc: +misc +---- - Patterns can now use shell escape sequences, - Added .editorconfig file, - Split documentation into topics, - The code is now split into several individual libraries. -windows: +windows +------- - Get rid of QtIFW and uses NSIS, WIX on Windows, - Installer have components, @@ -215,22 +235,22 @@ - Added better support for cross-compiling using MinGW. irccd 2.0.3 2016-11-01 ----------------------- +====================== - Fix various errors in logger plugin, - Fix quakenet support in auth plugin. irccd 2.0.2 2016-04-19 ----------------------- +====================== - Fix CMake error preventing installation of irccd and irccdctl. irccd 2.0.1 2016-03-13 ----------------------- +====================== - Plugin plugin: fix invalid usage. irccd 2.0.0 2016-03-01 ----------------------- +====================== - Initial 2.0.0 release. diff -r bbb3d3075ec2 -r 3ea3361f0fc7 CMakeLists.txt diff -r bbb3d3075ec2 -r 3ea3361f0fc7 CONTRIBUTE.md diff -r bbb3d3075ec2 -r 3ea3361f0fc7 CREDITS.md --- a/CREDITS.md Sun Feb 14 10:11:03 2021 +0100 +++ b/CREDITS.md Tue Feb 16 18:37:22 2021 +0100 @@ -16,3 +16,17 @@ - uriparser, https://uriparser.github.io Simple URI parser. + +Individual +---------- + +People for using, commenting and reporting errors: + +- Pierre Choffet, +- Yoan Giraud, +- Léo Villeveygoux. + +Some people on the *##irc* channel on freenode for their detailed information: + +- Andrio, +- jackal. diff -r bbb3d3075ec2 -r 3ea3361f0fc7 INSTALL.md diff -r bbb3d3075ec2 -r 3ea3361f0fc7 LICENSE.md diff -r bbb3d3075ec2 -r 3ea3361f0fc7 MIGRATING.md --- a/MIGRATING.md Sun Feb 14 10:11:03 2021 +0100 +++ b/MIGRATING.md Tue Feb 16 18:37:22 2021 +0100 @@ -78,6 +78,16 @@ which must be string (password is optional). - The property `commandChar` which is provided in both the `Server` constructor and the `Server.info` returned object has been renamed to `prefix`. +- The event `onMode` now takes four arguments: server, channel, mode and list + of arguments to the mode. The previous signature was mostly unusable. + +Plugins +------- + +**logger** + +- Due to the `onMode` change the template `mode` no longer takes `limit`, + `user` and `mask` but a string `args` instead. Migrating from 2.x to 3.x ========================= diff -r bbb3d3075ec2 -r 3ea3361f0fc7 README.md --- a/README.md Sun Feb 14 10:11:03 2021 +0100 +++ b/README.md Tue Feb 16 18:37:22 2021 +0100 @@ -33,10 +33,3 @@ ------ The irccd application was written by David Demelier - -Contributors ------------- - -- Pierre Choffet, -- Yoan Giraud, -- Léo Villeveygoux. diff -r bbb3d3075ec2 -r 3ea3361f0fc7 STYLE.md diff -r bbb3d3075ec2 -r 3ea3361f0fc7 cmake/IrccdDefinePlugin.cmake diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/LICENSE.libduktape.txt diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/LICENSE.libgreatest.txt diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/VERSION.libduktape.txt diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/VERSION.libgreatest.txt diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/CHANGES.md diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/CMakeLists.txt diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/CREDITS.md diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/LICENSE.md diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/README.md diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/extern/queue/sys/queue.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/src/basename.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/src/compat.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/src/compat.h.in diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/src/dirname.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/src/err.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/src/errc.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/src/errx.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/src/getopt.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/src/getprogname.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/src/pledge.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/src/reallocarray.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/src/recallocarray.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/src/setprogname.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/src/strdup.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/src/strlcat.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/src/strlcpy.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/src/strndup.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/src/strnlen.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/src/strsep.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/src/strtok_r.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/src/strtonum.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/src/verr.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/src/verrc.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/src/verrx.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/src/vsyslog.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/src/vwarn.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/src/vwarnc.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/src/vwarnx.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/src/warn.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/src/warnc.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/src/warnx.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/tests/CMakeLists.txt diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/tests/test-bsd.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/tests/test-dirent.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/tests/test-dlfcn.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/tests/test-posix.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/win/dirent/dirent.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/win/dlfcn/CMakeLists.txt diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/win/dlfcn/dlfcn.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libcompat/win/dlfcn/dlfcn.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libduktape/CMakeLists.txt diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libduktape/duk_config.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libduktape/duktape.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libduktape/duktape.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libgreatest/CMakeLists.txt diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libgreatest/greatest.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libketopt/CMakeLists.txt diff -r bbb3d3075ec2 -r 3ea3361f0fc7 extern/libketopt/ketopt.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/CMakeLists.txt diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/conf.y diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/dl-plugin.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/dl-plugin.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/js-plugin.c --- a/irccd/js-plugin.c Sun Feb 14 10:11:03 2021 +0100 +++ b/irccd/js-plugin.c Tue Feb 16 18:37:22 2021 +0100 @@ -96,6 +96,19 @@ } static void +push_modes(duk_context *ctx, char **modes) +{ + size_t i = 0; + + duk_push_array(ctx); + + for (char **mode = modes; mode && *mode; ++mode) { + duk_push_string(ctx, *mode); + duk_put_prop_index(ctx, -2, i++); + } +} + +static void push_names(duk_context *ctx, const struct irc_event *ev) { const char *token; @@ -104,7 +117,7 @@ duk_push_array(ctx); for (size_t i = 0; (token = strtok_r(p, " ", &p)); ++i) { - irc_server_strip(ev->server, &token, NULL, NULL); + irc_server_strip(ev->server, &token); duk_push_string(ctx, token); duk_put_prop_index(ctx, -2, i); } @@ -113,9 +126,6 @@ static void push_whois(duk_context *ctx, const struct irc_event *ev) { - const char *token; - char *p = ev->whois.channels; - duk_push_object(ctx); duk_push_string(ctx, ev->whois.nickname); duk_put_prop_string(ctx, -2, "nickname"); @@ -126,19 +136,16 @@ duk_push_string(ctx, ev->whois.hostname); duk_put_prop_string(ctx, -2, "hostname"); duk_push_array(ctx); - for (size_t i = 0; (token = strtok_r(p, " ", &p)); ++i) { - char mode = 0, prefix = 0; - irc_server_strip(ev->server, &token, &mode, &prefix); + for (size_t i = 0; i < ev->whois.channelsz; ++i) { duk_push_object(ctx); - duk_push_string(ctx, token); + duk_push_string(ctx, ev->whois.channels[i].name); duk_put_prop_string(ctx, -2, "channel"); - duk_push_sprintf(ctx, "%c", mode); - duk_put_prop_string(ctx, -2, "mode"); - duk_push_sprintf(ctx, "%c", prefix); - duk_put_prop_string(ctx, -2, "prefix"); + duk_push_int(ctx, ev->whois.channels[i].modes); + duk_put_prop_string(ctx, -2, "modes"); duk_put_prop_index(ctx, -2, i); } + duk_put_prop_string(ctx, -2, "channels"); } @@ -373,9 +380,8 @@ ev->message.channel, ev->message.message); break; case IRC_EVENT_MODE: - call(plg, "onMode", "Ss sss ss", ev->server, ev->mode.origin, - ev->mode.channel, ev->mode.mode, ev->mode.limit, - ev->mode.user, ev->mode.mask); + call(plg, "onMode", "Ss ssx", ev->server, ev->mode.origin, + ev->mode.channel, ev->mode.mode, push_modes, ev->mode.args); break; case IRC_EVENT_NAMES: call(plg, "onNames", "Ss x", ev->server, ev->names.channel, diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/js-plugin.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/jsapi-chrono.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/jsapi-chrono.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/jsapi-directory.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/jsapi-directory.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/jsapi-file.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/jsapi-file.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/jsapi-hook.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/jsapi-hook.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/jsapi-irccd.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/jsapi-irccd.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/jsapi-logger.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/jsapi-logger.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/jsapi-plugin.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/jsapi-plugin.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/jsapi-rule.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/jsapi-rule.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/jsapi-server.c --- a/irccd/jsapi-server.c Sun Feb 14 10:11:03 2021 +0100 +++ b/irccd/jsapi-server.c Tue Feb 16 18:37:22 2021 +0100 @@ -167,6 +167,24 @@ duk_push_string(ctx, s->ident.username); duk_put_prop_string(ctx, -2, "username"); + /* Prefixes. */ + duk_push_array(ctx); + + for (size_t i = 0; i < IRC_UTIL_SIZE(s->params.prefixes); ++i) { + if (s->params.prefixes[i].mode == 0) + continue; + + duk_push_object(ctx); + duk_push_string(ctx, (char []) { s->params.prefixes[i].mode, '\0' }); + duk_put_prop_string(ctx, -2, "mode"); + duk_push_string(ctx, (char []) { s->params.prefixes[i].symbol, '\0' }); + duk_put_prop_string(ctx, -2, "symbol"); + duk_put_prop_index(ctx, -2, i); + } + + duk_put_prop_string(ctx, -2, "prefixes"); + + /* Channels. */ duk_push_array(ctx); LIST_FOREACH(c, &s->channels, link) { @@ -181,11 +199,8 @@ duk_push_object(ctx); duk_push_string(ctx, u->nickname); duk_put_prop_string(ctx, -2, "nickname"); - if (u->mode) - duk_push_sprintf(ctx, "%c", u->mode); - else - duk_push_null(ctx); - duk_put_prop_string(ctx, -2, "mode"); + duk_push_int(ctx, u->modes); + duk_put_prop_string(ctx, -2, "modes"); duk_put_prop_index(ctx, -2, ui++); } diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/jsapi-server.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/jsapi-system.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/jsapi-system.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/jsapi-timer.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/jsapi-timer.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/jsapi-unicode.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/jsapi-unicode.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/jsapi-util.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/jsapi-util.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/lex.l diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/main.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/peer.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/peer.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/transport.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/transport.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/unicode.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccd/unicode.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccdctl/CMakeLists.txt diff -r bbb3d3075ec2 -r 3ea3361f0fc7 irccdctl/main.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 lib/CMakeLists.txt diff -r bbb3d3075ec2 -r 3ea3361f0fc7 lib/IrccdConfig.cmake diff -r bbb3d3075ec2 -r 3ea3361f0fc7 lib/irccd.pc diff -r bbb3d3075ec2 -r 3ea3361f0fc7 lib/irccd/channel.c --- a/lib/irccd/channel.c Sun Feb 14 10:11:03 2021 +0100 +++ b/lib/irccd/channel.c Tue Feb 16 18:37:22 2021 +0100 @@ -24,18 +24,6 @@ #include "compat.h" #include "util.h" -static inline struct irc_channel_user * -find(const struct irc_channel *ch, const char *nickname) -{ - struct irc_channel_user *u; - - LIST_FOREACH(u, &ch->users, link) - if (strcmp(u->nickname, nickname) == 0) - return u; - - return NULL; -} - struct irc_channel * irc_channel_new(const char *name, const char *password, int joined) { @@ -55,44 +43,33 @@ } void -irc_channel_add(struct irc_channel *ch, const char *nickname, char mode, char symbol) +irc_channel_add(struct irc_channel *ch, const char *nickname, int modes) { assert(ch); assert(nickname); struct irc_channel_user *user; - if (find(ch, nickname)) + if (irc_channel_find(ch, nickname)) return; user = irc_util_malloc(sizeof (*user)); - user->mode = mode; - user->symbol = symbol; + user->modes = modes; strlcpy(user->nickname, nickname, sizeof (user->nickname)); LIST_INSERT_HEAD(&ch->users, user, link); } -void -irc_channel_update(struct irc_channel *ch, - const char *nickname, - const char *newnickname, - char mode, - char symbol) +struct irc_channel_user * +irc_channel_find(struct irc_channel *ch, const char *nickname) { - assert(ch); - assert(nickname); + struct irc_channel_user *u; - struct irc_channel_user *user; + LIST_FOREACH(u, &ch->users, link) + if (strcmp(u->nickname, nickname) == 0) + return u; - if ((user = find(ch, nickname))) { - if (newnickname) - strlcpy(user->nickname, newnickname, sizeof (user->nickname)); - if (mode != -1 && symbol != -1) { - user->mode = mode; - user->symbol = symbol; - } - } + return NULL; } void @@ -115,8 +92,10 @@ struct irc_channel_user *user; - if ((user = find(ch, nick))) + if ((user = irc_channel_find(ch, nick))) { LIST_REMOVE(user, link); + free(user); + } } void diff -r bbb3d3075ec2 -r 3ea3361f0fc7 lib/irccd/channel.h --- a/lib/irccd/channel.h Sun Feb 14 10:11:03 2021 +0100 +++ b/lib/irccd/channel.h Tue Feb 16 18:37:22 2021 +0100 @@ -26,8 +26,7 @@ struct irc_channel_user { char nickname[IRC_NICKNAME_LEN]; - char mode; - char symbol; + int modes; LIST_ENTRY(irc_channel_user) link; }; @@ -45,10 +44,10 @@ irc_channel_new(const char *, const char *, int); void -irc_channel_add(struct irc_channel *, const char *, char, char); +irc_channel_add(struct irc_channel *, const char *, int); -void -irc_channel_update(struct irc_channel *, const char *, const char *, char, char); +struct irc_channel_user * +irc_channel_find(struct irc_channel *, const char *); void irc_channel_clear(struct irc_channel *); diff -r bbb3d3075ec2 -r 3ea3361f0fc7 lib/irccd/config.h.in diff -r bbb3d3075ec2 -r 3ea3361f0fc7 lib/irccd/conn.c --- a/lib/irccd/conn.c Sun Feb 14 10:11:03 2021 +0100 +++ b/lib/irccd/conn.c Tue Feb 16 18:37:22 2021 +0100 @@ -27,6 +27,8 @@ #include "compat.h" #include "conn.h" +#include "log.h" +#include "server.h" #include "util.h" static void @@ -122,9 +124,13 @@ { switch (SSL_get_error(conn->ssl, ret)) { case SSL_ERROR_WANT_READ: + irc_log_debug("server %s: step %d now needs read condition", + conn->sv->name, conn->ssl_step); conn->ssl_cond = IRC_CONN_SSL_ACT_READ; break; case SSL_ERROR_WANT_WRITE: + irc_log_debug("server %s: step %d now needs write condition", + conn->sv->name, conn->ssl_step); conn->ssl_cond = IRC_CONN_SSL_ACT_WRITE; break; case SSL_ERROR_SSL: @@ -142,10 +148,14 @@ int nr; if ((nr = SSL_read(conn->ssl, dst, dstsz)) <= 0) { + irc_log_debug("server %s: SSL read incomplete", conn->sv->name); conn->ssl_step = IRC_CONN_SSL_ACT_READ; return update_ssl_state(conn, nr); } + if (conn->ssl_cond) + irc_log_debug("server %s: condition back to normal", conn->sv->name); + conn->ssl_cond = IRC_CONN_SSL_ACT_NONE; conn->ssl_step = IRC_CONN_SSL_ACT_NONE; @@ -189,10 +199,14 @@ int ns; if ((ns = SSL_write(conn->ssl, conn->out, strlen(conn->out))) <= 0) { + irc_log_debug("server %s: SSL write incomplete", conn->sv->name); conn->ssl_step = IRC_CONN_SSL_ACT_WRITE; return update_ssl_state(conn, ns); } + if (conn->ssl_cond) + irc_log_debug("server %s: condition back to normal", conn->sv->name); + conn->ssl_cond = IRC_CONN_SSL_ACT_NONE; conn->ssl_step = IRC_CONN_SSL_ACT_NONE; @@ -271,8 +285,10 @@ dial(struct irc_conn *conn) { /* No more address available. */ - if (conn->aip == NULL) + if (conn->aip == NULL) { + irc_log_warn("server %s: could not connect", conn->sv->name); return irc_conn_disconnect(conn), -1; + } for (; conn->aip; conn->aip = conn->aip->ai_next) { if (create(conn) < 0) @@ -308,7 +324,7 @@ snprintf(service, sizeof (service), "%hu", conn->port); if ((ret = getaddrinfo(conn->hostname, service, &hints, &conn->ai)) != 0) { - // irc_log_warn gai_strerror(ret) + irc_log_warn("server %s: %s", conn->sv->name, gai_strerror(ret)); return -1; } @@ -336,9 +352,11 @@ #if defined(IRCCD_WITH_SSL) switch (conn->ssl_cond) { case IRC_CONN_SSL_ACT_READ: + irc_log_debug("server %s: need read condition", conn->sv->name); pfd->events |= POLLIN; break; case IRC_CONN_SSL_ACT_WRITE: + irc_log_debug("server %s: need write condition", conn->sv->name); pfd->events |= POLLOUT; break; default: @@ -352,6 +370,8 @@ static inline int renegotiate(struct irc_conn *conn) { + irc_log_debug("server %s: renegociate step=%d", conn->sv->name, conn->ssl_step); + return conn->ssl_step == IRC_CONN_SSL_ACT_READ ? input(conn) : output(conn); @@ -417,12 +437,16 @@ case IRC_CONN_STATE_READY: if (pfd->revents & (POLLERR | POLLHUP)) return irc_conn_disconnect(conn), -1; - if (conn->ssl_cond && renegotiate(conn) < 0) - return irc_conn_disconnect(conn), -1; - if (pfd->revents & POLLIN && input(conn) < 0) - return irc_conn_disconnect(conn), -1; - if (pfd->revents & POLLOUT && output(conn) < 0) - return irc_conn_disconnect(conn), -1; + + if (conn->ssl_cond) { + if (renegotiate(conn) < 0) + return irc_conn_disconnect(conn), -1; + } else { + if (pfd->revents & POLLIN && input(conn) < 0) + return irc_conn_disconnect(conn), -1; + if (pfd->revents & POLLOUT && output(conn) < 0) + return irc_conn_disconnect(conn), -1; + } break; default: break; diff -r bbb3d3075ec2 -r 3ea3361f0fc7 lib/irccd/conn.h --- a/lib/irccd/conn.h Sun Feb 14 10:11:03 2021 +0100 +++ b/lib/irccd/conn.h Tue Feb 16 18:37:22 2021 +0100 @@ -30,6 +30,8 @@ struct addrinfo; struct pollfd; +struct irc_server; + enum irc_conn_state { IRC_CONN_STATE_NONE, /* Nothing, default. */ IRC_CONN_STATE_CONNECTING, /* Pending connect(2) call. */ @@ -61,6 +63,7 @@ char out[IRC_BUF_LEN]; enum irc_conn_state state; enum irc_conn_flags flags; + struct irc_server *sv; #if defined(IRCCD_WITH_SSL) SSL_CTX *ctx; diff -r bbb3d3075ec2 -r 3ea3361f0fc7 lib/irccd/event.c --- a/lib/irccd/event.c Sun Feb 14 10:11:03 2021 +0100 +++ b/lib/irccd/event.c Tue Feb 16 18:37:22 2021 +0100 @@ -66,12 +66,13 @@ ev->message.message); break; case IRC_EVENT_MODE: - written = snprintf(str, strsz, "EVENT-MODE %s %s %s %s %s %s %s", + snprintf(str, strsz, "EVENT-MODE %s %s %s %s ", ev->server->name, ev->mode.origin, ev->mode.channel, - ev->mode.mode, - ev->mode.limit ? ev->mode.limit : "", - ev->mode.user ? ev->mode.user : "", - ev->mode.mask ? ev->mode.mask : ""); + ev->mode.mode); + + for (char **mode = ev->mode.args; *mode; ++mode) + written = strlcat(str, *mode, strsz); + break; case IRC_EVENT_NICK: written = snprintf(str, strsz, "EVENT-NICK %s %s %s", @@ -93,9 +94,11 @@ ev->topic.topic); break; case IRC_EVENT_WHOIS: +#if 0 snprintf(str, strsz, "EVENT-WHOIS %s %s %s %s %s %s", ev->server->name, ev->whois.nickname, ev->whois.username, ev->whois.realname, ev->whois.hostname, ev->whois.channels); +#endif break; default: break; @@ -135,9 +138,9 @@ free(ev->mode.origin); free(ev->mode.channel); free(ev->mode.mode); - free(ev->mode.limit); - free(ev->mode.user); - free(ev->mode.mask); + for (char **p = ev->mode.args; p && *p; ++p) + free(*p); + free(ev->mode.args); break; case IRC_EVENT_NAMES: free(ev->names.channel); @@ -167,6 +170,8 @@ free(ev->whois.username); free(ev->whois.realname); free(ev->whois.hostname); + for (size_t i = 0; i < ev->whois.channelsz; ++i) + free(ev->whois.channels[i].name); free(ev->whois.channels); break; default: diff -r bbb3d3075ec2 -r 3ea3361f0fc7 lib/irccd/event.h --- a/lib/irccd/event.h Sun Feb 14 10:11:03 2021 +0100 +++ b/lib/irccd/event.h Tue Feb 16 18:37:22 2021 +0100 @@ -81,9 +81,7 @@ char *origin; char *channel; char *mode; - char *limit; - char *user; - char *mask; + char **args; }; struct irc_event_names { @@ -119,7 +117,11 @@ char *username; char *realname; char *hostname; - char *channels; + struct { + char *name; + int modes; + } *channels; + size_t channelsz; }; struct irc_event { diff -r bbb3d3075ec2 -r 3ea3361f0fc7 lib/irccd/hook.c --- a/lib/irccd/hook.c Sun Feb 14 10:11:03 2021 +0100 +++ b/lib/irccd/hook.c Tue Feb 16 18:37:22 2021 +0100 @@ -52,6 +52,27 @@ } static char ** +alloc_mode(const struct irc_hook *h, const struct irc_event *ev) +{ + size_t n = 6; + char **ret; + + /* Ret contains now 6 values. */ + ret = alloc(h, 5, "onMode", ev->server->name, ev->mode.origin, + ev->mode.channel, ev->mode.mode); + + for (char **mode = ev->mode.args; *mode; ++mode) { + ret = irc_util_reallocarray(ret, n + 1, sizeof (char *)); + ret[n++] = *mode; + }; + + ret = irc_util_reallocarray(ret, n + 1, sizeof (char *)); + ret[n] = NULL; + + return ret; +} + +static char ** make_args(const struct irc_hook *h, const struct irc_event *ev) { char **ret; @@ -64,44 +85,42 @@ ret = alloc(h, 2, "onDisconnect", ev->server->name); break; case IRC_EVENT_INVITE: - ret = alloc(h, 3, "onInvite", ev->server->name, ev->invite.origin, + ret = alloc(h, 4, "onInvite", ev->server->name, ev->invite.origin, ev->invite.channel); break; case IRC_EVENT_JOIN: - ret = alloc(h, 3, "onJoin", ev->server->name, ev->join.origin, + ret = alloc(h, 4, "onJoin", ev->server->name, ev->join.origin, ev->join.channel); break; case IRC_EVENT_KICK: - ret = alloc(h, 5, "onKick", ev->server->name, ev->kick.origin, + ret = alloc(h, 6, "onKick", ev->server->name, ev->kick.origin, ev->kick.channel, ev->kick.target, ev->kick.reason); break; case IRC_EVENT_ME: - ret = alloc(h, 4, "onMe", ev->server->name, ev->message.origin, + ret = alloc(h, 5, "onMe", ev->server->name, ev->message.origin, ev->message.channel, ev->message.message); break; case IRC_EVENT_MESSAGE: - ret = alloc(h, 4, "onMessage", ev->server->name, ev->message.origin, + ret = alloc(h, 5, "onMessage", ev->server->name, ev->message.origin, ev->message.channel, ev->message.message); break; case IRC_EVENT_MODE: - ret = alloc(h, 7, "onMode", ev->server->name, ev->mode.origin, - ev->mode.channel, ev->mode.mode, ev->mode.limit, - ev->mode.user, ev->mode.mask); + ret = alloc_mode(h, ev); break; case IRC_EVENT_NICK: - ret = alloc(h, 3, "onNick", ev->server->name, ev->nick.origin, + ret = alloc(h, 4, "onNick", ev->server->name, ev->nick.origin, ev->nick.nickname); break; case IRC_EVENT_NOTICE: - ret = alloc(h, 4, "onNotice", ev->server->name, ev->notice.origin, + ret = alloc(h, 5, "onNotice", ev->server->name, ev->notice.origin, ev->notice.channel, ev->notice.notice); break; case IRC_EVENT_PART: - ret = alloc(h, 4, "onPart", ev->server->name, ev->part.origin, + ret = alloc(h, 5, "onPart", ev->server->name, ev->part.origin, ev->part.channel, ev->part.reason); break; case IRC_EVENT_TOPIC: - ret = alloc(h, 4, "onTopic", ev->server->name, ev->topic.origin, + ret = alloc(h, 5, "onTopic", ev->server->name, ev->topic.origin, ev->topic.channel, ev->topic.topic); break; default: diff -r bbb3d3075ec2 -r 3ea3361f0fc7 lib/irccd/hook.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 lib/irccd/irccd.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 lib/irccd/irccd.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 lib/irccd/limits.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 lib/irccd/log.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 lib/irccd/log.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 lib/irccd/plugin.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 lib/irccd/plugin.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 lib/irccd/rule.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 lib/irccd/rule.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 lib/irccd/server.c --- a/lib/irccd/server.c Sun Feb 14 10:11:03 2021 +0100 +++ b/lib/irccd/server.c Tue Feb 16 18:37:22 2021 +0100 @@ -79,15 +79,6 @@ return strncmp(s->ident.nickname, nick, strlen(s->ident.nickname)) == 0; } -static void -add_nick(const struct irc_server *s, struct irc_channel *ch, const char *nick) -{ - char mode = 0, prefix = 0; - - irc_server_strip(s, &nick, &mode, &prefix); - irc_channel_add(ch, nick, mode, prefix); -} - static struct irc_channel * add_channel(struct irc_server *s, const char *name, const char *password, int joined) { @@ -147,6 +138,16 @@ return line; } +static inline int +find_mode(struct irc_server *s, int mode) +{ + for (size_t i = 0; i < IRC_UTIL_SIZE(s->params.prefixes); ++i) + if (s->params.prefixes[i].mode == mode) + return i; + + return 0; +} + static void read_support_prefix(struct irc_server *s, const char *value) { @@ -159,11 +160,11 @@ if (sscanf(value, fmt, modes, tokens) == 2) { char *pm = modes; - char *tk = tokens; + char *sm = tokens; - for (size_t i = 0; i < IRC_UTIL_SIZE(s->params.prefixes) && *pm && *tk; ++i) { + for (size_t i = 0; i < IRC_UTIL_SIZE(s->params.prefixes) && *pm && *sm; ++i) { s->params.prefixes[i].mode = *pm++; - s->params.prefixes[i].token = *tk++; + s->params.prefixes[i].symbol = *sm++; } } } @@ -331,15 +332,64 @@ (void)ev; (void)msg; + int action = 0, mode; + size_t nelem = 0, argindex = 2; + struct irc_channel *ch; + struct irc_channel_user *u; + ev->type = IRC_EVENT_MODE; - ev->mode.origin = strdup(msg->prefix); - ev->mode.channel = strdup(msg->args[0]); - ev->mode.mode = strdup(msg->args[1]); - ev->mode.limit = msg->args[2] ? strdup(msg->args[2]) : NULL; - ev->mode.user = msg->args[3] ? strdup(msg->args[3]) : NULL; - ev->mode.mask = msg->args[4] ? strdup(msg->args[4]) : NULL; + ev->mode.origin = irc_util_strdup(msg->prefix); + ev->mode.channel = irc_util_strdup(msg->args[0]); + ev->mode.mode = irc_util_strdup(msg->args[1]); + + /* Create a NULL-sentineled list of arguments. */ + for (size_t i = 2; i < IRC_ARGS_MAX && msg->args[i]; ++i) { + ev->mode.args = irc_util_reallocarray(ev->mode.args, nelem + 1, sizeof (char *)); + ev->mode.args[nelem++] = irc_util_strdup(msg->args[i]); + } + + /* Add the NULL sentinel. */ + ev->mode.args = irc_util_reallocarray(ev->mode.args, nelem + 1, sizeof (char *)); + ev->mode.args[nelem] = NULL; + + if (!(ch = irc_server_find(s, ev->mode.channel))) + return; + + for (const char *p = ev->mode.mode; *p; ++p) { + /* Determine if we're adding or removing a mode. */ + if (*p == '+' || *p == '-') { + action = *p; + continue; + } - /* TODO: update nickname modes. */ + /* All these mode require an argument but we don't use. */ + switch (*p) { + case 'b': + case 'k': + case 'l': + case 'e': + case 'I': + ++argindex; + continue; + } + + /* Find which mode this symbol is (e.g. o=@). */ + if ((mode = find_mode(s, *p)) == 0) { + ++argindex; + continue; + } + if (!msg->args[argindex] || !(u = irc_channel_find(ch, msg->args[argindex]))) { + ++argindex; + continue; + } + + ++argindex; + + if (action == '+') + u->modes |= (1 << mode); + else + u->modes &= ~(1 << mode); + } } static void @@ -433,35 +483,34 @@ static void handle_names(struct irc_server *s, struct irc_event *ev, struct irc_conn_msg *msg) { - (void)s; (void)ev; - (void)msg; struct irc_channel *ch; char *p, *token; + int modes = 0; ch = add_channel(s, msg->args[2], NULL, 1); /* Track existing nicknames into the given channel. */ - for (p = msg->args[3]; (token = strtok_r(p, " ", &p)); ) - if (strlen(token) > 0) - add_nick(s, ch, token); + for (p = msg->args[3]; (token = strtok_r(p, " ", &p)); ) { + if (strlen(token) == 0) + continue; + + modes = irc_server_strip(s, (const char **)&token); + irc_channel_add(ch, token, modes); + } } static void handle_endofnames(struct irc_server *s, struct irc_event *ev, struct irc_conn_msg *msg) { - (void)s; - (void)ev; - (void)msg; - FILE *fp; size_t length; const struct irc_channel *ch; const struct irc_channel_user *u; ev->type = IRC_EVENT_NAMES; - ev->names.channel = strdup(msg->args[1]); + ev->names.channel = irc_util_strdup(msg->args[1]); /* Construct a string list for every user in the channel. */ ch = irc_server_find(s, ev->names.channel); @@ -470,8 +519,9 @@ err(1, "open_memstream"); LIST_FOREACH(u, &ch->users, link) { - if (u->symbol) - fprintf(fp, "%c", u->symbol); + for (size_t i = 0; i < IRC_UTIL_SIZE(s->params.prefixes); ++i) + if (u->modes & (1 << i)) + fprintf(fp, "%c", s->params.prefixes[i].symbol); fprintf(fp, "%s", u->nickname); @@ -521,26 +571,23 @@ { (void)ev; - size_t curlen, reqlen; + char *token, *p; + int modes; - curlen = s->bufwhois.channels ? strlen(s->bufwhois.channels) : 0; - reqlen = strlen(msg->args[2]); + if (!msg->args[2]) + return; - /* - * If there is already something, add a space at the end of the current - * buffer. - */ - if (curlen > 0) - reqlen++; + for (p = msg->args[2]; (token = strtok_r(p, " ", &p)); ) { + modes = irc_server_strip(s, (const char **)&token); + s->bufwhois.channels = irc_util_reallocarray( + s->bufwhois.channels, + s->bufwhois.channelsz + 1, + sizeof (*s->bufwhois.channels) + ); - /* Now, don't forget */ - s->bufwhois.channels = irc_util_realloc(s->bufwhois.channels, reqlen + 1); - - if (curlen > 0) { - strcat(s->bufwhois.channels, " "); - strcat(s->bufwhois.channels, msg->args[2]); - } else - strcpy(s->bufwhois.channels, msg->args[2]); + s->bufwhois.channels[s->bufwhois.channelsz].name = irc_util_strdup(token); + s->bufwhois.channels[s->bufwhois.channelsz++].modes = modes; + } } static void @@ -615,12 +662,21 @@ { s->state = IRC_SERVER_STATE_CONNECTED; + /* + * Use multi-prefix extension to keep track of all combined "modes" in + * a channel. + * + * https://ircv3.net/specs/extensions/multi-prefix-3.1.html + */ + irc_server_send(s, "CAP REQ :multi-prefix"); + if (s->ident.password[0]) irc_server_send(s, "PASS %s", s->ident.password); irc_server_send(s, "NICK %s", s->ident.nickname); irc_server_send(s, "USER %s %s %s :%s", s->ident.username, s->ident.username, s->ident.username, s->ident.realname); + irc_server_send(s, "CAP END"); } struct irc_server * @@ -667,6 +723,8 @@ if (s->flags & IRC_SERVER_FLAGS_SSL) s->conn.flags |= IRC_CONN_SSL; + s->conn.sv = s; + if (irc_conn_connect(&s->conn) < 0) fail(s); else @@ -952,27 +1010,22 @@ return irc_server_send(s, "WHOIS %s", target); } -void -irc_server_strip(const struct irc_server *s, const char **nick, char *mode, char *prefix) +int +irc_server_strip(const struct irc_server *s, const char **what) { assert(s); - assert(*nick); + assert(*what); - if (mode) - *mode = 0; - if (prefix) - *prefix = 0; + int modes = 0; for (size_t i = 0; i < IRC_UTIL_SIZE(s->params.prefixes); ++i) { - if (**nick == s->params.prefixes[i].token) { - if (mode) - *mode = s->params.prefixes[i].mode; - if (prefix) - *prefix = s->params.prefixes[i].token; - *nick += 1; - break; + if (**what == s->params.prefixes[i].symbol) { + modes |= 1 << i; + *what += 1; } } + + return modes; } void diff -r bbb3d3075ec2 -r 3ea3361f0fc7 lib/irccd/server.h --- a/lib/irccd/server.h Sun Feb 14 10:11:03 2021 +0100 +++ b/lib/irccd/server.h Tue Feb 16 18:37:22 2021 +0100 @@ -75,7 +75,7 @@ unsigned int kicklen; struct { char mode; /* Mode (e.g. ov). */ - char token; /* Symbol used (e.g. @+). */ + char symbol; /* Symbol used (e.g. @+). */ } prefixes[IRC_USERMODES_LEN]; }; @@ -166,8 +166,8 @@ int irc_server_whois(struct irc_server *, const char *); -void -irc_server_strip(const struct irc_server *, const char **, char *, char *); +int +irc_server_strip(const struct irc_server *, const char **); void irc_server_split(const char *, struct irc_server_user *); diff -r bbb3d3075ec2 -r 3ea3361f0fc7 lib/irccd/subst.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 lib/irccd/subst.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 lib/irccd/util.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 lib/irccd/util.h diff -r bbb3d3075ec2 -r 3ea3361f0fc7 man/CMakeLists.txt diff -r bbb3d3075ec2 -r 3ea3361f0fc7 man/irccd-api-chrono.3 diff -r bbb3d3075ec2 -r 3ea3361f0fc7 man/irccd-api-directory.3 diff -r bbb3d3075ec2 -r 3ea3361f0fc7 man/irccd-api-file.3 diff -r bbb3d3075ec2 -r 3ea3361f0fc7 man/irccd-api-hook.3 diff -r bbb3d3075ec2 -r 3ea3361f0fc7 man/irccd-api-logger.3 diff -r bbb3d3075ec2 -r 3ea3361f0fc7 man/irccd-api-plugin.3 diff -r bbb3d3075ec2 -r 3ea3361f0fc7 man/irccd-api-rule.3 diff -r bbb3d3075ec2 -r 3ea3361f0fc7 man/irccd-api-server.3 --- a/man/irccd-api-server.3 Sun Feb 14 10:11:03 2021 +0100 +++ b/man/irccd-api-server.3 Tue Feb 16 18:37:22 2021 +0100 @@ -82,7 +82,7 @@ .Fa parameters object which may have the following properties: .Pp -.Bl -tag -compact -width "hostname (string)" +.Bl -tag -width "hostname (string)" .It Fa name No (string) The unique identifier name. .It Fa hostname No (string) @@ -115,7 +115,7 @@ method returns the server information. The object have the following properties: .Pp -.Bl -tag -compact -width "hostname (string)" +.Bl -tag -width "hostname (string)" .It Va name No (string) The server unique name. .It Va hostname No (string) @@ -125,19 +125,17 @@ .It Va ssl No (bool) True if using ssl. .It Va channels No (array) -An array of all channels. Each channel in the returned array contain the -following properties: -.Bl -tag -width xxx +An array of all channels as objects. Each channel in the returned array contain +the following properties: +.Bl -tag -width "name (string)" .It Va name No (string) The channel name. .It Va joined No (bool) True if the daemon is actually present on this channel. .It Va users No (array) -An array of users that consists of objects with three properties: -.Va nickname , mode -and -.Va symbol -as their nickname, the channel mode and the symbol representing this mode. +An array of users that consists of objects with two properties: +.Va nickname No (string) and modes Fa (int) +as their nickname and modes as bitwise mask for this channel. .El .Pp .It Va realname No (string) diff -r bbb3d3075ec2 -r 3ea3361f0fc7 man/irccd-api-system.3 diff -r bbb3d3075ec2 -r 3ea3361f0fc7 man/irccd-api-timer.3 diff -r bbb3d3075ec2 -r 3ea3361f0fc7 man/irccd-api-unicode.3 diff -r bbb3d3075ec2 -r 3ea3361f0fc7 man/irccd-api-util.3 diff -r bbb3d3075ec2 -r 3ea3361f0fc7 man/irccd-api.3 --- a/man/irccd-api.3 Sun Feb 14 10:11:03 2021 +0100 +++ b/man/irccd-api.3 Tue Feb 16 18:37:22 2021 +0100 @@ -46,7 +46,7 @@ .Fn onLoad " .Fn onMe "server, origin, channel, message" .Fn onMessage "server, origin, channel, message" -.Fn onMode "server, origin, channel, mode, limit, user, mask" +.Fn onMode "server, origin, channel, mode, args" .Fn onNames "server, channel, list" .Fn onNick "server, origin, nickname" .Fn onNotice "server, origin, notice" @@ -199,6 +199,8 @@ The person who changed the mode. .It Fa mode No (string) The new mode. +.It Fa args No (array) +List of mode arguments as strings. .El .\" onNames .Ss onNames @@ -293,7 +295,7 @@ The .Fa info is an object with the following properties: -.Bl -tag -width 20n -compact -offset Ds +.Bl -tag -width "nickname (string)" .It Fa nickname No (string) The user nickname. .It Fa user No (string) @@ -303,7 +305,14 @@ .It Fa realname No (string) The real name used. .It Fa channels No (array) -An optional list of channels joined. +An optional list of channels joined by the user. Objects in the array are +defined using the following properties: +.Bl -tag -width "name (string)" +.It Fa name No (string) +The name of the channel. +.It Fa modes No (int) +A bitwise mask of modes applied the user has on this channel. +.El .El .\" MODULES .Sh MODULES diff -r bbb3d3075ec2 -r 3ea3361f0fc7 man/irccd-ipc.7 diff -r bbb3d3075ec2 -r 3ea3361f0fc7 man/irccd-templates.7 diff -r bbb3d3075ec2 -r 3ea3361f0fc7 man/irccd-test.1 diff -r bbb3d3075ec2 -r 3ea3361f0fc7 man/irccd.1 diff -r bbb3d3075ec2 -r 3ea3361f0fc7 man/irccd.conf.5 diff -r bbb3d3075ec2 -r 3ea3361f0fc7 man/irccdctl.1 diff -r bbb3d3075ec2 -r 3ea3361f0fc7 plugins/CMakeLists.txt diff -r bbb3d3075ec2 -r 3ea3361f0fc7 plugins/ask/CMakeLists.txt diff -r bbb3d3075ec2 -r 3ea3361f0fc7 plugins/ask/ask.7 diff -r bbb3d3075ec2 -r 3ea3361f0fc7 plugins/ask/ask.js diff -r bbb3d3075ec2 -r 3ea3361f0fc7 plugins/auth/CMakeLists.txt diff -r bbb3d3075ec2 -r 3ea3361f0fc7 plugins/auth/auth.7 diff -r bbb3d3075ec2 -r 3ea3361f0fc7 plugins/auth/auth.js diff -r bbb3d3075ec2 -r 3ea3361f0fc7 plugins/hangman/CMakeLists.txt diff -r bbb3d3075ec2 -r 3ea3361f0fc7 plugins/hangman/hangman.7 diff -r bbb3d3075ec2 -r 3ea3361f0fc7 plugins/hangman/hangman.js diff -r bbb3d3075ec2 -r 3ea3361f0fc7 plugins/history/CMakeLists.txt diff -r bbb3d3075ec2 -r 3ea3361f0fc7 plugins/history/history.7 diff -r bbb3d3075ec2 -r 3ea3361f0fc7 plugins/history/history.js diff -r bbb3d3075ec2 -r 3ea3361f0fc7 plugins/joke/CMakeLists.txt diff -r bbb3d3075ec2 -r 3ea3361f0fc7 plugins/joke/joke.7 diff -r bbb3d3075ec2 -r 3ea3361f0fc7 plugins/joke/joke.js diff -r bbb3d3075ec2 -r 3ea3361f0fc7 plugins/links/CMakeLists.txt diff -r bbb3d3075ec2 -r 3ea3361f0fc7 plugins/links/links.7 diff -r bbb3d3075ec2 -r 3ea3361f0fc7 plugins/links/links.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 plugins/logger/CMakeLists.txt diff -r bbb3d3075ec2 -r 3ea3361f0fc7 plugins/logger/logger.7 diff -r bbb3d3075ec2 -r 3ea3361f0fc7 plugins/logger/logger.js --- a/plugins/logger/logger.js Sun Feb 14 10:11:03 2021 +0100 +++ b/plugins/logger/logger.js Tue Feb 16 18:37:22 2021 +0100 @@ -41,7 +41,7 @@ "me": "%H:%M:%S * #{nickname} #{message}", "message": "%H:%M:%S #{nickname}: #{message}", "invite": "%H:%M:%S #{nickname} invited you on #{channel}", - "mode": "%H:%M:%S :: #{nickname} set mode #{channel} #{mode} #{limit} #{user} #{mask}", + "mode": "%H:%M:%S :: #{nickname} set mode #{channel} #{mode} #{args}", "notice": "%H:%M:%S [notice] #{channel} (#{nickname}) #{message}", "part": "%H:%M:%S << #{nickname} left #{channel} [#{reason}]", "query": "%H:%M:%S #{nickname}: #{message}", @@ -135,15 +135,14 @@ })); } -function onMode(server, origin, channel, mode, limit, user, mask) +function onMode(server, origin, channel, mode, args) { origin = origin.toLowerCase(); + channel = channel.toLowerCase(); write("mode", keywords(server, channel, origin, { "mode": mode, - "limit": limit, - "user": user, - "mask": mask + "args": args.join(" "), })); } @@ -155,6 +154,7 @@ function onNotice(server, origin, channel, notice) { origin = origin.toLowerCase(); + channel = channel.toLowerCase(); write("notice", keywords(server, channel, origin, { "message": notice, diff -r bbb3d3075ec2 -r 3ea3361f0fc7 plugins/plugin/CMakeLists.txt diff -r bbb3d3075ec2 -r 3ea3361f0fc7 plugins/plugin/plugin.7 diff -r bbb3d3075ec2 -r 3ea3361f0fc7 plugins/plugin/plugin.js diff -r bbb3d3075ec2 -r 3ea3361f0fc7 plugins/roulette/CMakeLists.txt diff -r bbb3d3075ec2 -r 3ea3361f0fc7 plugins/roulette/roulette.7 diff -r bbb3d3075ec2 -r 3ea3361f0fc7 plugins/roulette/roulette.js diff -r bbb3d3075ec2 -r 3ea3361f0fc7 plugins/tictactoe/CMakeLists.txt diff -r bbb3d3075ec2 -r 3ea3361f0fc7 plugins/tictactoe/tictactoe.7 diff -r bbb3d3075ec2 -r 3ea3361f0fc7 plugins/tictactoe/tictactoe.js diff -r bbb3d3075ec2 -r 3ea3361f0fc7 systemd/irccd.service diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/CMakeLists.txt diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/data/answers.conf diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/data/error.json diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/data/example-dl-plugin.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/data/example-plugin.js diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/data/joke/error-empty.json diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/data/joke/error-invalid.json diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/data/joke/error-not-array.json diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/data/joke/error-toobig.json diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/data/joke/jokes.json diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/data/root/file-1.txt diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/data/root/level-1/level-2/file-2.txt diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/data/root/lines.txt diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/data/timer.js diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/data/words-seq.conf diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/data/words.conf diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/test-bot.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/test-channel.c --- a/tests/test-channel.c Sun Feb 14 10:11:03 2021 +0100 +++ b/tests/test-channel.c Tue Feb 16 18:37:22 2021 +0100 @@ -32,40 +32,33 @@ GREATEST_ASSERT_STR_EQ("", ch->password); GREATEST_ASSERT(ch->joined); - irc_channel_add(ch, "markand", 'o', '@'); + irc_channel_add(ch, "markand", 1); user = LIST_FIRST(&ch->users); - GREATEST_ASSERT_EQ('o', user->mode); - GREATEST_ASSERT_EQ('@', user->symbol); + GREATEST_ASSERT_EQ(1, user->modes); GREATEST_ASSERT_STR_EQ("markand", user->nickname); - irc_channel_add(ch, "markand", '+', '@'); + irc_channel_add(ch, "markand", 2); user = LIST_FIRST(&ch->users); - GREATEST_ASSERT_EQ('o', user->mode); - GREATEST_ASSERT_EQ('@', user->symbol); + GREATEST_ASSERT_EQ(1, user->modes); GREATEST_ASSERT_STR_EQ("markand", user->nickname); - irc_channel_add(ch, "jean", 'h', '+'); + irc_channel_add(ch, "jean", 4); user = LIST_FIRST(&ch->users); - GREATEST_ASSERT_EQ('h', user->mode); - GREATEST_ASSERT_EQ('+', user->symbol); + GREATEST_ASSERT_EQ(4, user->modes); GREATEST_ASSERT_STR_EQ("jean", user->nickname); user = LIST_NEXT(user, link); - GREATEST_ASSERT_EQ('o', user->mode); - GREATEST_ASSERT_EQ('@', user->symbol); + GREATEST_ASSERT_EQ(1, user->modes); GREATEST_ASSERT_STR_EQ("markand", user->nickname); - irc_channel_add(ch, "zoe", 0, 0); + irc_channel_add(ch, "zoe", 0); user = LIST_FIRST(&ch->users); - GREATEST_ASSERT_EQ(0, user->mode); - GREATEST_ASSERT_EQ(0, user->symbol); + GREATEST_ASSERT_EQ(0, user->modes); GREATEST_ASSERT_STR_EQ("zoe", user->nickname); user = LIST_NEXT(user, link); - GREATEST_ASSERT_EQ('h', user->mode); - GREATEST_ASSERT_EQ('+', user->symbol); + GREATEST_ASSERT_EQ(4, user->modes); GREATEST_ASSERT_STR_EQ("jean", user->nickname); user = LIST_NEXT(user, link); - GREATEST_ASSERT_EQ('o', user->mode); - GREATEST_ASSERT_EQ('@', user->symbol); + GREATEST_ASSERT_EQ(1, user->modes); GREATEST_ASSERT_STR_EQ("markand", user->nickname); irc_channel_finish(ch); @@ -81,24 +74,21 @@ ch = irc_channel_new("#test", NULL, 1); - irc_channel_add(ch, "markand", 'o', '@'); - irc_channel_add(ch, "jean", 0, 0); - irc_channel_add(ch, "zoe", 0, 0); + irc_channel_add(ch, "markand", 1); + irc_channel_add(ch, "jean", 0); + irc_channel_add(ch, "zoe", 0); irc_channel_remove(ch, "jean"); user = LIST_FIRST(&ch->users); - GREATEST_ASSERT_EQ(0, user->mode); - GREATEST_ASSERT_EQ(0, user->symbol); + GREATEST_ASSERT_EQ(0, user->modes); GREATEST_ASSERT_STR_EQ("zoe", user->nickname); user = LIST_NEXT(user, link); - GREATEST_ASSERT_EQ('o', user->mode); - GREATEST_ASSERT_EQ('@', user->symbol); + GREATEST_ASSERT_EQ(1, user->modes); GREATEST_ASSERT_STR_EQ("markand", user->nickname); irc_channel_remove(ch, "zoe"); user = LIST_FIRST(&ch->users); - GREATEST_ASSERT_EQ('o', user->mode); - GREATEST_ASSERT_EQ('@', user->symbol); + GREATEST_ASSERT_EQ(1, user->modes); GREATEST_ASSERT_STR_EQ("markand", user->nickname); irc_channel_remove(ch, "markand"); @@ -109,40 +99,10 @@ GREATEST_PASS(); } -GREATEST_TEST -basics_update(void) -{ - struct irc_channel *ch; - struct irc_channel_user *user; - - ch = irc_channel_new("#test", NULL, 1); - - irc_channel_add(ch, "markand", 'o', '@'); - irc_channel_add(ch, "jean", 0, 0); - irc_channel_add(ch, "zoe", 0, 0); - - irc_channel_update(ch, "zoe", NULL, 'o', '@'); - user = LIST_FIRST(&ch->users); - GREATEST_ASSERT_EQ('o', user->mode); - GREATEST_ASSERT_EQ('@', user->symbol); - GREATEST_ASSERT_STR_EQ("zoe", user->nickname); - - irc_channel_update(ch, "zoe", "eoz", -1, -1); - user = LIST_FIRST(&ch->users); - GREATEST_ASSERT_EQ('o', user->mode); - GREATEST_ASSERT_EQ('@', user->symbol); - GREATEST_ASSERT_STR_EQ("eoz", user->nickname); - - irc_channel_finish(ch); - - GREATEST_PASS(); -} - GREATEST_SUITE(suite_basics) { GREATEST_RUN_TEST(basics_add); GREATEST_RUN_TEST(basics_remove); - GREATEST_RUN_TEST(basics_update); } GREATEST_MAIN_DEFS(); diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/test-dl-plugin.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/test-event.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/test-jsapi-chrono.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/test-jsapi-directory.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/test-jsapi-file.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/test-jsapi-irccd.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/test-jsapi-system.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/test-jsapi-timer.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/test-jsapi-unicode.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/test-jsapi-util.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/test-log.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/test-plugin-ask.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/test-plugin-auth.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/test-plugin-hangman.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/test-plugin-history.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/test-plugin-joke.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/test-plugin-logger.c --- a/tests/test-plugin-logger.c Sun Feb 14 10:11:03 2021 +0100 +++ b/tests/test-plugin-logger.c Tue Feb 16 18:37:22 2021 +0100 @@ -43,13 +43,12 @@ if (!plugin) errx(1, "could not load plugin"); - irc_log_to_console(); irc_server_incref(server); irc_plugin_set_template(plugin, "join", "join=#{server}:#{channel}:#{origin}:#{nickname}"); irc_plugin_set_template(plugin, "kick", "kick=#{server}:#{channel}:#{origin}:#{nickname}:#{target}:#{reason}"); irc_plugin_set_template(plugin, "me", "me=#{server}:#{channel}:#{origin}:#{nickname}:#{message}"); irc_plugin_set_template(plugin, "message", "message=#{server}:#{channel}:#{origin}:#{nickname}:#{message}"); - irc_plugin_set_template(plugin, "mode", "mode=#{server}:#{origin}:#{channel}:#{mode}:#{limit}:#{user}:#{mask}"); + irc_plugin_set_template(plugin, "mode", "mode=#{server}:#{origin}:#{channel}:#{mode}:#{args}"); irc_plugin_set_template(plugin, "notice", "notice=#{server}:#{origin}:#{channel}:#{message}"); irc_plugin_set_template(plugin, "part", "part=#{server}:#{channel}:#{origin}:#{nickname}:#{reason}"); irc_plugin_set_template(plugin, "query", "query=#{server}:#{origin}:#{nickname}:#{message}"); @@ -166,15 +165,13 @@ .server = server, .mode = { .origin = "jean!jean@localhost", - .channel = "chris", - .mode = "+i", - .limit = "l", - .user = "u", - .mask = "m" + .channel = "#staff", + .mode = "+ov", + .args = (char *[]) { "francis", "benoit", NULL } } }); - GREATEST_ASSERT_STR_EQ("mode=test:jean!jean@localhost:chris:+i:l:u:m", last()); + GREATEST_ASSERT_STR_EQ("mode=test:jean!jean@localhost:#staff:+ov:francis benoit", last()); GREATEST_PASS(); } diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/test-plugin-plugin.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/test-plugin-tictactoe.c --- a/tests/test-plugin-tictactoe.c Sun Feb 14 10:11:03 2021 +0100 +++ b/tests/test-plugin-tictactoe.c Tue Feb 16 18:37:22 2021 +0100 @@ -81,8 +81,8 @@ /* We need tw players on a channel to play the game. */ irc_server_join(server, "#tictactoe", NULL); - irc_channel_add(LIST_FIRST(&server->channels), "a", 0, 0); - irc_channel_add(LIST_FIRST(&server->channels), "b", 0, 0); + irc_channel_add(LIST_FIRST(&server->channels), "a", 0); + irc_channel_add(LIST_FIRST(&server->channels), "b", 0); /* Fake server connected to send data. */ server->state = IRC_SERVER_STATE_CONNECTED; diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/test-rule.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/test-subst.c diff -r bbb3d3075ec2 -r 3ea3361f0fc7 tests/test-util.c