diff options
author | June McEnroe <june@causal.agency> | 2020-02-27 02:36:32 -0500 |
---|---|---|
committer | June McEnroe <june@causal.agency> | 2020-02-27 02:36:32 -0500 |
commit | 793f564ffd9622e2c879b1ee3591748d602d6118 (patch) | |
tree | cc556825581fa1e81ccd4246ad84ae1f2d972970 | |
parent | Support cap-notify (diff) | |
download | pounce-793f564ffd9622e2c879b1ee3591748d602d6118.tar.gz pounce-793f564ffd9622e2c879b1ee3591748d602d6118.zip |
Support CAP LS 302 from clients
-rw-r--r-- | bounce.h | 10 | ||||
-rw-r--r-- | client.c | 16 | ||||
-rw-r--r-- | pounce.1 | 13 | ||||
-rw-r--r-- | state.c | 4 |
4 files changed, 32 insertions, 11 deletions
diff --git a/bounce.h b/bounce.h index 1655772..5aff027 100644 --- a/bounce.h +++ b/bounce.h @@ -87,7 +87,9 @@ enum Cap { #define X(name, id) BIT(id), ENUM_CAP #undef X - TagCaps = CapAccountTag + CapBits, + TagCaps = 0 + | CapAccountTag | CapBatch | CapLabeledResponse | CapMessageTags @@ -118,13 +120,17 @@ static inline enum Cap capParse(const char *list) { return caps; } -static inline const char *capList(enum Cap caps) { +static inline const char *capList(enum Cap caps, const char *values[CapBits]) { static char buf[1024]; buf[0] = '\0'; for (size_t i = 0; i < ARRAY_LEN(CapNames); ++i) { if (caps & (1 << i)) { if (buf[0]) strlcat(buf, " ", sizeof(buf)); strlcat(buf, CapNames[i], sizeof(buf)); + if (values && values[i]) { + strlcat(buf, "=", sizeof(buf)); + strlcat(buf, values[i], sizeof(buf)); + } } } return buf; diff --git a/client.c b/client.c index 2d5b8e0..f66ea0e 100644 --- a/client.c +++ b/client.c @@ -166,6 +166,7 @@ static void handleCap(struct Client *client, struct Message *msg) { if (!msg->params[0]) msg->params[0] = ""; enum Cap avail = CapServerTime | CapPassive | (stateCaps & ~CapSASL); + const char *values[CapBits] = { [CapSASLBit] = "EXTERNAL" }; if (clientCA) avail |= CapSASL; if (!strcmp(msg->params[0], "END")) { @@ -175,7 +176,18 @@ static void handleCap(struct Client *client, struct Message *msg) { } else if (!strcmp(msg->params[0], "LS")) { if (client->need) client->need |= NeedCapEnd; - clientFormat(client, ":%s CAP * LS :%s\r\n", ORIGIN, capList(avail)); + if (msg->params[1] && !strcmp(msg->params[1], "302")) { + if (avail & CapCapNotify) client->caps |= CapCapNotify; + clientFormat( + client, ":%s CAP * LS :%s\r\n", + ORIGIN, capList(avail, values) + ); + } else { + clientFormat( + client, ":%s CAP * LS :%s\r\n", + ORIGIN, capList(avail, NULL) + ); + } } else if (!strcmp(msg->params[0], "REQ") && msg->params[1]) { if (client->need) client->need |= NeedCapEnd; @@ -190,7 +202,7 @@ static void handleCap(struct Client *client, struct Message *msg) { } else if (!strcmp(msg->params[0], "LIST")) { clientFormat( client, ":%s CAP * LIST :%s\r\n", - ORIGIN, capList(client->caps) + ORIGIN, capList(client->caps, NULL) ); } else { diff --git a/pounce.1 b/pounce.1 index ef28279..0ab6210 100644 --- a/pounce.1 +++ b/pounce.1 @@ -525,9 +525,12 @@ daemon implements the following: .%A Perry Lorier .%A Kevin L. Mitchell .%A William Pitcock -.%T IRCv3.1 Client Capability Negotiation +.%A Attila Molnar +.%A Daniel Oakley +.%A James Wheare +.%T IRCv3 Client Capability Negotiation .%I IRCv3 Working Group -.%U https://ircv3.net/specs/core/capability-negotiation-3.1.html +.%U https://ircv3.net/specs/core/capability-negotiation .Re . .It @@ -554,10 +557,10 @@ daemon implements the following: .It .Rs .%A William Pitcock -.%A Jilles Tjoelker -.%T IRCv3.1 SASL Authentication +.%A Attila Molnar +.%T IRCv3.2 SASL Authentication .%I IRCv3 Working Group -.%U https://ircv3.net/specs/extensions/sasl-3.1.html +.%U https://ircv3.net/specs/extensions/sasl-3.2 .Re . .It diff --git a/state.c b/state.c index d840018..71c2763 100644 --- a/state.c +++ b/state.c @@ -51,7 +51,7 @@ void stateLogin( serverFormat("CAP LS\r\n"); if (pass) serverFormat("PASS :%s\r\n", pass); if (sasl) { - serverFormat("CAP REQ :%s\r\n", capList(CapSASL)); + serverFormat("CAP REQ :%s\r\n", capList(CapSASL, NULL)); if (plain) { byte buf[AuthLen]; size_t len = 1 + strlen(plain); @@ -76,7 +76,7 @@ static void handleCap(struct Message *msg) { if (!strcmp(msg->params[1], "LS") || !strcmp(msg->params[1], "NEW")) { caps &= ~(CapSASL | CapUnsupported); - if (caps) serverFormat("CAP REQ :%s\r\n", capList(caps)); + if (caps) serverFormat("CAP REQ :%s\r\n", capList(caps, NULL)); } else if (!strcmp(msg->params[1], "ACK")) { stateCaps |= caps; |