]> arthur.barton.de Git - ngircd.git/commitdiff
"multi-prefix" capability 1/2: implement complete CAP infrastructure
authorAlexander Barton <alex@barton.de>
Fri, 27 Apr 2012 22:36:41 +0000 (00:36 +0200)
committerAlexander Barton <alex@barton.de>
Fri, 27 Apr 2012 22:36:41 +0000 (00:36 +0200)
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
src/ngircd/irc-cap.c

index e477dc004ea13a1965c8f39608149b79345bb582..5532d3310aa0df658f7f58580bb1ccf8aed742b1 100644 (file)
@@ -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));
index c92a3f392dd38fea3a3aa53ab225460dc3898ff2..a6923ac62da0425548b81398d9935afab36d2512 100644 (file)
@@ -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- */