[BACK]Return to irc-cap.c CVS log [TXT][DIR] Up to [local] / ircnowd / src / ngircd

Annotation of ircnowd/src/ngircd/irc-cap.c, Revision 1.1

1.1     ! tomglok     1: /*
        !             2:  * ngIRCd -- The Next Generation IRC Daemon
        !             3:  * Copyright (c)2001-2014 Alexander Barton (alex@barton.de) and Contributors.
        !             4:  *
        !             5:  * This program is free software; you can redistribute it and/or modify
        !             6:  * it under the terms of the GNU General Public License as published by
        !             7:  * the Free Software Foundation; either version 2 of the License, or
        !             8:  * (at your option) any later version.
        !             9:  * Please read the file COPYING, README and AUTHORS for more information.
        !            10:  */
        !            11:
        !            12: #include "portab.h"
        !            13:
        !            14: /**
        !            15:  * @file
        !            16:  * Handler for IRC capability ("CAP") commands
        !            17:  */
        !            18:
        !            19: #include <assert.h>
        !            20: #include <string.h>
        !            21: #include <strings.h>
        !            22:
        !            23: #include "conn.h"
        !            24: #include "channel.h"
        !            25: #include "client-cap.h"
        !            26: #include "irc-write.h"
        !            27: #include "log.h"
        !            28: #include "login.h"
        !            29: #include "messages.h"
        !            30: #include "parse.h"
        !            31:
        !            32: #include "irc-cap.h"
        !            33:
        !            34: /* Local functions */
        !            35:
        !            36: /**
        !            37:  * Set CAP negotiation status and mark client as "supports capabilities".
        !            38:  *
        !            39:  * @param Client The client to handle.
        !            40:  */
        !            41: static void
        !            42: Set_CAP_Negotiation(CLIENT *Client)
        !            43: {
        !            44:        assert(Client != NULL);
        !            45:
        !            46:        if (Client_Type(Client) != CLIENT_USER)
        !            47:                Client_CapAdd(Client, CLIENT_CAP_PENDING);
        !            48:        Client_CapAdd(Client, CLIENT_CAP_SUPPORTED);
        !            49: }
        !            50:
        !            51: /**
        !            52:  * Parse capability string and return numeric flag value.
        !            53:  *
        !            54:  * @param Args The string containing space-separated capability names.
        !            55:  * @return Changed capability flags or 0 on error.
        !            56:  */
        !            57: static int
        !            58: Parse_CAP(int Capabilities, char *Args)
        !            59: {
        !            60:        static char tmp[COMMAND_LEN];
        !            61:        char *ptr;
        !            62:
        !            63:        assert(Args != NULL);
        !            64:
        !            65:        strlcpy(tmp, Args, sizeof(tmp));
        !            66:
        !            67:        ptr = strtok(tmp, " ");
        !            68:        while (ptr) {
        !            69:                if (*ptr == '-') {
        !            70:                        /* drop capabilities */
        !            71:                        ptr++;
        !            72:                        if (strcmp(ptr, "multi-prefix") == 0)
        !            73:                                Capabilities &= ~CLIENT_CAP_MULTI_PREFIX;
        !            74:                        else
        !            75:                                return -1;
        !            76:                } else {
        !            77:                        /* request capabilities */
        !            78:                        if (strcmp(ptr, "multi-prefix") == 0)
        !            79:                                Capabilities |= CLIENT_CAP_MULTI_PREFIX;
        !            80:                        else
        !            81:                                return -1;
        !            82:                }
        !            83:                ptr = strtok(NULL, " ");
        !            84:        }
        !            85:
        !            86:        return Capabilities;
        !            87: }
        !            88:
        !            89: /**
        !            90:  * Return textual representation of capability flags.
        !            91:  *
        !            92:  * Please note: this function returns a pointer to a global buffer and
        !            93:  * therefore isn't thread safe!
        !            94:  *
        !            95:  * @param Capabilities Capability flags (bitmask).
        !            96:  * @return Pointer to textual representation.
        !            97:  */
        !            98: static char *
        !            99: Get_CAP_String(int Capabilities)
        !           100: {
        !           101:        static char txt[COMMAND_LEN];
        !           102:
        !           103:        txt[0] = '\0';
        !           104:
        !           105:        if (Capabilities & CLIENT_CAP_MULTI_PREFIX)
        !           106:                strlcat(txt, "multi-prefix ", sizeof(txt));
        !           107:
        !           108:        return txt;
        !           109: }
        !           110:
        !           111: /**
        !           112:  * Handler for the IRCv3 sub-command "CAP LS".
        !           113:  *
        !           114:  * @param Client The client from which this command has been received.
        !           115:  * @param Arg Command argument or NULL.
        !           116:  * @return CONNECTED or DISCONNECTED.
        !           117:  */
        !           118: static bool
        !           119: Handle_CAP_LS(CLIENT *Client, UNUSED char *Arg)
        !           120: {
        !           121:        assert(Client != NULL);
        !           122:
        !           123:        Set_CAP_Negotiation(Client);
        !           124:
        !           125:        return IRC_WriteStrClient(Client,
        !           126:                                  "CAP %s LS :multi-prefix",
        !           127:                                  Client_ID(Client));
        !           128: }
        !           129:
        !           130: /**
        !           131:  * Handler for the IRCv3 sub-command "CAP LIST".
        !           132:  *
        !           133:  * @param Client The client from which this command has been received.
        !           134:  * @param Arg Command argument or NULL.
        !           135:  * @return CONNECTED or DISCONNECTED.
        !           136:  */
        !           137: static bool
        !           138: Handle_CAP_LIST(CLIENT *Client, UNUSED char *Arg)
        !           139: {
        !           140:        assert(Client != NULL);
        !           141:
        !           142:        return IRC_WriteStrClient(Client, "CAP %s LIST :%s", Client_ID(Client),
        !           143:                                  Get_CAP_String(Client_Cap(Client)));
        !           144: }
        !           145:
        !           146: /**
        !           147:  * Handler for the IRCv3 sub-command "CAP REQ".
        !           148:  *
        !           149:  * @param Client The client from which this command has been received.
        !           150:  * @param Arg Command argument.
        !           151:  * @return CONNECTED or DISCONNECTED.
        !           152:  */
        !           153: static bool
        !           154: Handle_CAP_REQ(CLIENT *Client, char *Arg)
        !           155: {
        !           156:        int new_cap;
        !           157:
        !           158:        assert(Client != NULL);
        !           159:        assert(Arg != NULL);
        !           160:
        !           161:        Set_CAP_Negotiation(Client);
        !           162:
        !           163:        new_cap = Parse_CAP(Client_Cap(Client), Arg);
        !           164:
        !           165:        if (new_cap < 0)
        !           166:                return IRC_WriteStrClient(Client, "CAP %s NAK :%s",
        !           167:                                          Client_ID(Client), Arg);
        !           168:
        !           169:        Client_CapSet(Client, new_cap);
        !           170:        return IRC_WriteStrClient(Client, "CAP %s ACK :%s",
        !           171:                                  Client_ID(Client), Arg);
        !           172: }
        !           173:
        !           174: /**
        !           175:  * Handler for the IRCv3 sub-command "CAP ACK".
        !           176:  *
        !           177:  * @param Client The client from which this command has been received.
        !           178:  * @param Arg Command argument.
        !           179:  * @return CONNECTED or DISCONNECTED.
        !           180:  */
        !           181: static bool
        !           182: Handle_CAP_ACK(UNUSED CLIENT *Client, UNUSED char *Arg)
        !           183: {
        !           184:        assert(Client != NULL);
        !           185:        assert(Arg != NULL);
        !           186:
        !           187:        return CONNECTED;
        !           188: }
        !           189:
        !           190: /**
        !           191:  * Handler for the IRCv3 sub-command "CAP CLEAR".
        !           192:  *
        !           193:  * @param Client The client from which this command has been received.
        !           194:  * @return CONNECTED or DISCONNECTED.
        !           195:  */
        !           196: static bool
        !           197: Handle_CAP_CLEAR(CLIENT *Client)
        !           198: {
        !           199:        int cap_old;
        !           200:
        !           201:        assert(Client != NULL);
        !           202:
        !           203:        cap_old = Client_Cap(Client);
        !           204:        if (cap_old & CLIENT_CAP_MULTI_PREFIX)
        !           205:                Client_CapDel(Client, CLIENT_CAP_MULTI_PREFIX);
        !           206:
        !           207:        return IRC_WriteStrClient(Client, "CAP %s ACK :%s", Client_ID(Client),
        !           208:                                  Get_CAP_String(cap_old));
        !           209: }
        !           210:
        !           211: /**
        !           212:  * Handler for the IRCv3 sub-command "CAP END".
        !           213:  *
        !           214:  * @param Client The client from which this command has been received.
        !           215:  * @return CONNECTED or DISCONNECTED.
        !           216:  */
        !           217: static bool
        !           218: Handle_CAP_END(CLIENT *Client)
        !           219: {
        !           220:        assert(Client != NULL);
        !           221:
        !           222:        if (Client_Type(Client) != CLIENT_USER) {
        !           223:                /* User is still logging in ... */
        !           224:                Client_CapDel(Client, CLIENT_CAP_PENDING);
        !           225:
        !           226:                if (Client_Type(Client) == CLIENT_WAITCAPEND) {
        !           227:                        /* Only "CAP END" was missing: log in! */
        !           228:                        return Login_User(Client);
        !           229:                }
        !           230:        }
        !           231:
        !           232:        return CONNECTED;
        !           233: }
        !           234:
        !           235: /* Global functions */
        !           236:
        !           237: /**
        !           238:  * Handler for the IRCv3 command "CAP".
        !           239:  *
        !           240:  * @param Client The client from which this command has been received.
        !           241:  * @param Req Request structure with prefix and all parameters.
        !           242:  * @return CONNECTED or DISCONNECTED.
        !           243:  */
        !           244: GLOBAL bool
        !           245: IRC_CAP(CLIENT *Client, REQUEST *Req)
        !           246: {
        !           247:        assert(Client != NULL);
        !           248:        assert(Req != NULL);
        !           249:
        !           250:        LogDebug("Got \"%s %s\" command from \"%s\" ...",
        !           251:                 Req->command, Req->argv[0], Client_ID(Client));
        !           252:
        !           253:        if (Req->argc == 1) {
        !           254:                if (strcasecmp(Req->argv[0], "CLEAR") == 0)
        !           255:                        return Handle_CAP_CLEAR(Client);
        !           256:                if (strcasecmp(Req->argv[0], "END") == 0)
        !           257:                        return Handle_CAP_END(Client);
        !           258:        }
        !           259:        if (Req->argc >= 1 && Req->argc <= 2) {
        !           260:                if (strcasecmp(Req->argv[0], "LS") == 0)
        !           261:                        return Handle_CAP_LS(Client, Req->argv[1]);
        !           262:                if (strcasecmp(Req->argv[0], "LIST") == 0)
        !           263:                        return Handle_CAP_LIST(Client, Req->argv[1]);
        !           264:        }
        !           265:        if (Req->argc == 2) {
        !           266:                if (strcasecmp(Req->argv[0], "REQ") == 0)
        !           267:                        return Handle_CAP_REQ(Client, Req->argv[1]);
        !           268:                if (strcasecmp(Req->argv[0], "ACK") == 0)
        !           269:                        return Handle_CAP_ACK(Client, Req->argv[1]);
        !           270:        }
        !           271:
        !           272:        return IRC_WriteErrClient(Client, ERR_INVALIDCAP_MSG,
        !           273:                                  Client_ID(Client), Req->argv[0]);
        !           274: }
        !           275:
        !           276: /* -eof- */

CVSweb