X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=ngircd-alex.git;a=blobdiff_plain;f=src%2Fngircd%2Firc-cap.c;h=42b0e4da9aa112b464d9754bb2f2632a5f41fedf;hp=af34c38c18403370f16f223eac257e429bc6fb3d;hb=08f9d31d60220e8a389a2d24f42625be7749f090;hpb=f37600ee01f6cfd86e8fa80f77ee26ebaf3012b2 diff --git a/src/ngircd/irc-cap.c b/src/ngircd/irc-cap.c index af34c38c..42b0e4da 100644 --- a/src/ngircd/irc-cap.c +++ b/src/ngircd/irc-cap.c @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors. + * Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,6 +24,7 @@ #include "conn.h" #include "channel.h" #include "client-cap.h" +#include "irc-macros.h" #include "irc-write.h" #include "log.h" #include "login.h" @@ -33,70 +34,91 @@ #include "exp.h" #include "irc-cap.h" -bool Handle_CAP_LS PARAMS((CLIENT *Client, char *Arg)); -bool Handle_CAP_LIST PARAMS((CLIENT *Client, char *Arg)); -bool Handle_CAP_REQ PARAMS((CLIENT *Client, char *Arg)); -bool Handle_CAP_ACK PARAMS((CLIENT *Client, char *Arg)); -bool Handle_CAP_CLEAR PARAMS((CLIENT *Client)); -bool Handle_CAP_END PARAMS((CLIENT *Client)); +/* Local functions */ -void Set_CAP_Negotiation PARAMS((CLIENT *Client)); +/** + * Set CAP negotiation status and mark client as "supports capabilities". + * + * @param Client The client to handle. + */ +static void +Set_CAP_Negotiation(CLIENT *Client) +{ + assert(Client != NULL); -int Parse_CAP PARAMS((int Capabilities, char *Args)); -char *Get_CAP_String PARAMS((int Capabilities)); + if (Client_Type(Client) != CLIENT_USER) + Client_CapAdd(Client, CLIENT_CAP_PENDING); + Client_CapAdd(Client, CLIENT_CAP_SUPPORTED); +} /** - * Handler for the IRCv3 "CAP" command. + * Parse capability string and return numeric flag value. * - * @param Client The client from which this command has been received. - * @param Req Request structure with prefix and all parameters. - * @returns CONNECTED or DISCONNECTED. + * @param Args The string containing space-separated capability names. + * @return Changed capability flags or 0 on error. */ -GLOBAL bool -IRC_CAP(CLIENT *Client, REQUEST *Req) +static int +Parse_CAP(int Capabilities, char *Args) { - assert(Client != NULL); - assert(Req != NULL); + static char tmp[COMMAND_LEN]; + char *ptr; - /* Bad number of prameters? */ - if (Req->argc < 1 || Req->argc > 2) - return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, - Client_ID(Client), Req->command); + assert(Args != NULL); - LogDebug("Got \"%s %s\" command from \"%s\" ...", - Req->command, Req->argv[0], Client_ID(Client)); + strlcpy(tmp, Args, sizeof(tmp)); - if (Req->argc == 1) { - if (strcasecmp(Req->argv[0], "CLEAR") == 0) - return Handle_CAP_CLEAR(Client); - if (strcasecmp(Req->argv[0], "END") == 0) - return Handle_CAP_END(Client); - } - if (Req->argc >= 1 && Req->argc <= 2) { - if (strcasecmp(Req->argv[0], "LS") == 0) - return Handle_CAP_LS(Client, Req->argv[1]); - if (strcasecmp(Req->argv[0], "LIST") == 0) - return Handle_CAP_LIST(Client, Req->argv[1]); - } - if (Req->argc == 2) { - if (strcasecmp(Req->argv[0], "REQ") == 0) - return Handle_CAP_REQ(Client, Req->argv[1]); - if (strcasecmp(Req->argv[0], "ACK") == 0) - return Handle_CAP_ACK(Client, Req->argv[1]); + 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 IRC_WriteStrClient(Client, ERR_INVALIDCAP_MSG, - Client_ID(Client), Req->argv[0]); + return Capabilities; } /** - * Handler for the "CAP LS" command. + * 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. + */ +static 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; +} + +/** + * Handler for the IRCv3 sub-command "CAP LS". * * @param Client The client from which this command has been received. * @param Arg Command argument or NULL. - * @returns CONNECTED or DISCONNECTED. + * @return CONNECTED or DISCONNECTED. */ -bool +static bool Handle_CAP_LS(CLIENT *Client, UNUSED char *Arg) { assert(Client != NULL); @@ -109,13 +131,13 @@ Handle_CAP_LS(CLIENT *Client, UNUSED char *Arg) } /** - * Handler for the "CAP LIST" command. + * Handler for the IRCv3 sub-command "CAP LIST". * * @param Client The client from which this command has been received. * @param Arg Command argument or NULL. - * @returns CONNECTED or DISCONNECTED. + * @return CONNECTED or DISCONNECTED. */ -bool +static bool Handle_CAP_LIST(CLIENT *Client, UNUSED char *Arg) { assert(Client != NULL); @@ -125,13 +147,13 @@ Handle_CAP_LIST(CLIENT *Client, UNUSED char *Arg) } /** - * Handler for the "CAP REQ" command. + * Handler for the IRCv3 sub-command "CAP REQ". * * @param Client The client from which this command has been received. * @param Arg Command argument. - * @returns CONNECTED or DISCONNECTED. + * @return CONNECTED or DISCONNECTED. */ -bool +static bool Handle_CAP_REQ(CLIENT *Client, char *Arg) { int new_cap; @@ -153,13 +175,13 @@ Handle_CAP_REQ(CLIENT *Client, char *Arg) } /** - * Handler for the "CAP ACK" command. + * Handler for the IRCv3 sub-command "CAP ACK". * * @param Client The client from which this command has been received. * @param Arg Command argument. - * @returns CONNECTED or DISCONNECTED. + * @return CONNECTED or DISCONNECTED. */ -bool +static bool Handle_CAP_ACK(UNUSED CLIENT *Client, UNUSED char *Arg) { assert(Client != NULL); @@ -169,12 +191,12 @@ Handle_CAP_ACK(UNUSED CLIENT *Client, UNUSED char *Arg) } /** - * Handler for the "CAP CLEAR" command. + * Handler for the IRCv3 sub-command "CAP CLEAR". * * @param Client The client from which this command has been received. - * @returns CONNECTED or DISCONNECTED. + * @return CONNECTED or DISCONNECTED. */ -bool +static bool Handle_CAP_CLEAR(CLIENT *Client) { int cap_old; @@ -190,12 +212,12 @@ Handle_CAP_CLEAR(CLIENT *Client) } /** - * Handler for the "CAP END" command. + * Handler for the IRCv3 sub-command "CAP END". * * @param Client The client from which this command has been received. - * @returns CONNECTED or DISCONNECTED. + * @return CONNECTED or DISCONNECTED. */ -bool +static bool Handle_CAP_END(CLIENT *Client) { assert(Client != NULL); @@ -213,79 +235,45 @@ Handle_CAP_END(CLIENT *Client) return CONNECTED; } -/** - * Set CAP negotiation status and mark client as "supports capabilities". - * - * @param Client The client to handle. - */ -void -Set_CAP_Negotiation(CLIENT *Client) -{ - assert(Client != NULL); - - if (Client_Type(Client) != CLIENT_USER) - Client_CapAdd(Client, CLIENT_CAP_PENDING); - Client_CapAdd(Client, CLIENT_CAP_SUPPORTED); -} +/* Global functions */ /** - * Parse capability string and return numeric flag value. + * Handler for the IRCv3 command "CAP". * - * @param Args The string containing space-separated capability names. - * @return Changed capability flags or 0 on error. + * @param Client The client from which this command has been received. + * @param Req Request structure with prefix and all parameters. + * @return CONNECTED or DISCONNECTED. */ -int -Parse_CAP(int Capabilities, char *Args) +GLOBAL bool +IRC_CAP(CLIENT *Client, REQUEST *Req) { - static char tmp[COMMAND_LEN]; - char *ptr; - - assert(Args != NULL); + assert(Client != NULL); + assert(Req != NULL); - strlcpy(tmp, Args, sizeof(tmp)); + LogDebug("Got \"%s %s\" command from \"%s\" ...", + Req->command, Req->argv[0], Client_ID(Client)); - 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, " "); + if (Req->argc == 1) { + if (strcasecmp(Req->argv[0], "CLEAR") == 0) + return Handle_CAP_CLEAR(Client); + if (strcasecmp(Req->argv[0], "END") == 0) + return Handle_CAP_END(Client); + } + if (Req->argc >= 1 && Req->argc <= 2) { + if (strcasecmp(Req->argv[0], "LS") == 0) + return Handle_CAP_LS(Client, Req->argv[1]); + if (strcasecmp(Req->argv[0], "LIST") == 0) + return Handle_CAP_LIST(Client, Req->argv[1]); + } + if (Req->argc == 2) { + if (strcasecmp(Req->argv[0], "REQ") == 0) + return Handle_CAP_REQ(Client, Req->argv[1]); + if (strcasecmp(Req->argv[0], "ACK") == 0) + return Handle_CAP_ACK(Client, Req->argv[1]); } - 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; + return IRC_WriteErrClient(Client, ERR_INVALIDCAP_MSG, + Client_ID(Client), Req->argv[0]); } /* -eof- */