Module: ngircd.git Branch: master Commit: 1d7e99531a6f713a04bbc91a6f7f2963c9ece75c URL: http://ngircd.barton.de/cgi-bin/gitweb.cgi?p=ngircd.git&a=commit;h=1d7e9...
Author: Alexander Barton alex@barton.de Date: Sat Apr 28 00:36:41 2012 +0200
"multi-prefix" capability 1/2: implement complete CAP infrastructure
Now ngIRCd is able to handle "CAP LS", "CAP REQ", "CAP LIST", and "CAP CLEAR" commands.
"multi-prefix" can be set/unset, but has no functionality - yet!
---
src/ngircd/client-cap.h | 2 + src/ngircd/irc-cap.c | 89 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 87 insertions(+), 4 deletions(-)
diff --git a/src/ngircd/client-cap.h b/src/ngircd/client-cap.h index e477dc0..5532d33 100644 --- a/src/ngircd/client-cap.h +++ b/src/ngircd/client-cap.h @@ -20,6 +20,8 @@ #define CLIENT_CAP_PENDING 1 /* Capability negotiation pending */ #define CLIENT_CAP_SUPPORTED 2 /* Client supports IRC capabilities */
+#define CLIENT_CAP_MULTI_PREFIX 4 /* multi-prefix */ + GLOBAL int Client_Cap PARAMS((CLIENT *Client));
GLOBAL void Client_CapSet PARAMS((CLIENT *Client, int Cap)); diff --git a/src/ngircd/irc-cap.c b/src/ngircd/irc-cap.c index c92a3f3..a6923ac 100644 --- a/src/ngircd/irc-cap.c +++ b/src/ngircd/irc-cap.c @@ -42,6 +42,8 @@ bool Handle_CAP_END PARAMS((CLIENT *Client));
void Set_CAP_Negotiation PARAMS((CLIENT *Client));
+int Parse_CAP PARAMS((int Capabilities, char *Args)); +char *Get_CAP_String PARAMS((int Capabilities));
/** * Handler for the IRCv3 "CAP" command. @@ -101,7 +103,9 @@ Handle_CAP_LS(CLIENT *Client, UNUSED char *Arg)
Set_CAP_Negotiation(Client);
- return IRC_WriteStrClient(Client, "CAP %s LS :", Client_ID(Client)); + return IRC_WriteStrClient(Client, + "CAP %s LS :multi-prefix", + Client_ID(Client)); }
/** @@ -116,7 +120,8 @@ Handle_CAP_LIST(CLIENT *Client, UNUSED char *Arg) { assert(Client != NULL);
- return IRC_WriteStrClient(Client, "CAP %s LIST :", Client_ID(Client)); + return IRC_WriteStrClient(Client, "CAP %s LIST :%s", Client_ID(Client), + Get_CAP_String(Client_Cap(Client))); }
/** @@ -129,12 +134,21 @@ Handle_CAP_LIST(CLIENT *Client, UNUSED char *Arg) bool Handle_CAP_REQ(CLIENT *Client, char *Arg) { + int new_cap; + assert(Client != NULL); assert(Arg != NULL);
Set_CAP_Negotiation(Client);
- return IRC_WriteStrClient(Client, "CAP %s NAK :%s", + new_cap = Parse_CAP(Client_Cap(Client), Arg); + + if (new_cap < 0) + return IRC_WriteStrClient(Client, "CAP %s NAK :%s", + Client_ID(Client), Arg); + + Client_CapSet(Client, new_cap); + return IRC_WriteStrClient(Client, "CAP %s ACK :%s", Client_ID(Client), Arg); }
@@ -163,9 +177,16 @@ Handle_CAP_ACK(CLIENT *Client, char *Arg) bool Handle_CAP_CLEAR(CLIENT *Client) { + int cap_old; + assert(Client != NULL);
- return IRC_WriteStrClient(Client, "CAP %s ACK :", Client_ID(Client)); + cap_old = Client_Cap(Client); + if (cap_old & CLIENT_CAP_MULTI_PREFIX) + Client_CapDel(Client, CLIENT_CAP_MULTI_PREFIX); + + return IRC_WriteStrClient(Client, "CAP %s ACK :%s", Client_ID(Client), + Get_CAP_String(cap_old)); }
/** @@ -207,4 +228,64 @@ Set_CAP_Negotiation(CLIENT *Client) Client_CapAdd(Client, CLIENT_CAP_SUPPORTED); }
+/** + * Parse capability string and return numeric flag value. + * + * @param Args The string containing space-separated capability names. + * @return Changed capability flags or 0 on error. + */ +int +Parse_CAP(int Capabilities, char *Args) +{ + static char tmp[COMMAND_LEN]; + char *ptr; + + assert(Args != NULL); + + strlcpy(tmp, Args, sizeof(tmp)); + + ptr = strtok(tmp, " "); + while (ptr) { + if (*ptr == '-') { + /* drop capabilities */ + ptr++; + if (strcmp(ptr, "multi-prefix") == 0) + Capabilities &= ~CLIENT_CAP_MULTI_PREFIX; + else + return -1; + } else { + /* request capabilities */ + if (strcmp(ptr, "multi-prefix") == 0) + Capabilities |= CLIENT_CAP_MULTI_PREFIX; + else + return -1; + } + ptr = strtok(NULL, " "); + } + + return Capabilities; +} + +/** + * Return textual representation of capability flags. + * + * Please note: this function returns a pointer to a global buffer and + * therefore isn't thread safe! + * + * @param Capabilities Capability flags (bitmask). + * @return Pointer to textual representation. + */ +char +*Get_CAP_String(int Capabilities) +{ + static char txt[COMMAND_LEN]; + + txt[0] = '\0'; + + if (Capabilities & CLIENT_CAP_MULTI_PREFIX) + strlcat(txt, "multi-prefix ", sizeof(txt)); + + return txt; +} + /* -eof- */