From 76c9ee11debf08dca9c850085435604da262c856 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Gomez?= Date: Sun, 4 Feb 2024 22:45:22 +0900 Subject: [PATCH] Handle CAP requests from clients, reply with no capabilities MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some clients require the server to handle CAP requests (IRCv3). This adds basic support for CAP requests during the authentication phase, sending no capabilities on CAP LS or CAP LIST, and CAP NAK with all requested capabilities listed on CAP REQ. This will be a base for adding capabilities later. Signed-off-by: Loïc Gomez --- src/irc.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/irc.c b/src/irc.c index 63a602d..88f9b4e 100644 --- a/src/irc.c +++ b/src/irc.c @@ -1030,6 +1030,31 @@ static int irc_cli_pass(bip_t *bip, struct link_client *ic, struct line *line) return OK_FORGET; } +static int irc_cli_cap(bip_t *bip, struct link_client *ic, struct line *line) +{ + if (irc_line_count(line) < 2) + return ERR_PROTOCOL; + + /* When we decide to enable actual capabilities, we'll have to handle CAP + * version, add a flag cap_started or similar, and handle CAP END. + */ + if (irc_line_elem_equals(line, 1, "LS")) { + WRITE_LINE2(CONN(ic), NULL, "CAP", "*", "LS"); + } else if (irc_line_elem_equals(line, 1, "LIST")) { + WRITE_LINE3(CONN(ic), NULL, "CAP", "*", "LIST", ""); + } else if (irc_line_elem_equals(line, 1, "REQ")) { + char *caps = irc_line_to_string_skip(line, 2); + if (caps) { + caps++; + WRITE_LINE3(CONN(ic), NULL, "CAP", "*", "NAK", caps); + } + } + + if ((ic->state & IRCC_READY) == IRCC_READY) + return irc_cli_startup(bip, ic, line); + return OK_FORGET; +} + static int irc_cli_quit(struct link_client *ic, struct line *line) { (void)ic; @@ -1408,6 +1433,8 @@ static int irc_dispatch_logging_client(bip_t *bip, struct link_client *ic, return irc_cli_user(bip, ic, line); } else if (irc_line_elem_equals(line, 0, "PASS")) { return irc_cli_pass(bip, ic, line); + } else if (irc_line_elem_equals(line, 0, "CAP")) { + return irc_cli_cap(bip, ic, line); } return OK_FORGET; }