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

Annotation of ircnowd/src/ngircd/irc-op.c, Revision 1.1.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:  * Channel operator commands
                     17:  */
                     18:
                     19: #include <assert.h>
                     20: #include <string.h>
                     21:
                     22: #include "conn.h"
                     23: #include "channel.h"
                     24: #include "irc-macros.h"
                     25: #include "irc-write.h"
                     26: #include "lists.h"
                     27: #include "log.h"
                     28: #include "messages.h"
                     29: #include "parse.h"
                     30:
                     31: #include "irc-op.h"
                     32:
                     33: /* Local functions */
                     34:
                     35: static bool
                     36: try_kick(CLIENT *peer, CLIENT* from, const char *nick, const char *channel,
                     37:         const char *reason)
                     38: {
                     39:        CLIENT *target = Client_Search(nick);
                     40:
                     41:        if (!target)
                     42:                return IRC_WriteErrClient(from, ERR_NOSUCHNICK_MSG,
                     43:                                          Client_ID(from), nick);
                     44:
                     45:        Channel_Kick(peer, target, from, channel, reason);
                     46:        return true;
                     47: }
                     48:
                     49: /* Global functions */
                     50:
                     51: /**
                     52:  * Handler for the IRC command "KICK".
                     53:  *
                     54:  * @param Client The client from which this command has been received.
                     55:  * @param Req Request structure with prefix and all parameters.
                     56:  * @return CONNECTED or DISCONNECTED.
                     57:  */
                     58: GLOBAL bool
                     59: IRC_KICK(CLIENT *Client, REQUEST *Req)
                     60: {
                     61:        CLIENT *from;
                     62:        char *itemList = Req->argv[0];
                     63:        const char* currentNick, *currentChannel, *reason;
                     64:        unsigned int channelCount = 1;
                     65:        unsigned int nickCount = 1;
                     66:
                     67:        assert( Client != NULL );
                     68:        assert( Req != NULL );
                     69:
                     70:        _IRC_GET_SENDER_OR_RETURN_(from, Req, Client)
                     71:
                     72:        while (*itemList) {
                     73:                if (*itemList == ',') {
                     74:                        *itemList = '\0';
                     75:                        channelCount++;
                     76:                }
                     77:                itemList++;
                     78:        }
                     79:
                     80:        itemList = Req->argv[1];
                     81:        while (*itemList) {
                     82:                if (*itemList == ',') {
                     83:                        *itemList = '\0';
                     84:                        nickCount++;
                     85:                }
                     86:                itemList++;
                     87:        }
                     88:
                     89:        reason = Req->argc == 3 ? Req->argv[2] : Client_ID(from);
                     90:        currentNick = Req->argv[1];
                     91:        currentChannel = Req->argv[0];
                     92:        if (channelCount == 1) {
                     93:                while (nickCount > 0) {
                     94:                        if (!try_kick(Client, from, currentNick,
                     95:                                      currentChannel, reason))
                     96:                                return false;
                     97:
                     98:                        while (*currentNick)
                     99:                                currentNick++;
                    100:
                    101:                        currentNick++;
                    102:                        nickCount--;
                    103:                }
                    104:        } else if (channelCount == nickCount) {
                    105:                while (nickCount > 0) {
                    106:                        if (!try_kick(Client, from, currentNick,
                    107:                                      currentChannel, reason))
                    108:                                return false;
                    109:
                    110:                        while (*currentNick)
                    111:                                currentNick++;
                    112:
                    113:                        while (*currentChannel)
                    114:                                currentChannel++;
                    115:
                    116:                        currentNick++;
                    117:                        currentChannel++;
                    118:                        nickCount--;
                    119:                }
                    120:        } else {
                    121:                return IRC_WriteErrClient(Client, ERR_NEEDMOREPARAMS_MSG,
                    122:                                        Client_ID(Client), Req->command);
                    123:        }
                    124:        return true;
                    125: } /* IRC_KICK */
                    126:
                    127: /**
                    128:  * Handler for the IRC command "INVITE".
                    129:  *
                    130:  * @param Client The client from which this command has been received.
                    131:  * @param Req Request structure with prefix and all parameters.
                    132:  * @return CONNECTED or DISCONNECTED.
                    133:  */
                    134: GLOBAL bool
                    135: IRC_INVITE(CLIENT *Client, REQUEST *Req)
                    136: {
                    137:        CHANNEL *chan;
                    138:        CLIENT *target, *from;
                    139:        const char *colon_if_necessary;
                    140:        bool remember = false;
                    141:
                    142:        assert( Client != NULL );
                    143:        assert( Req != NULL );
                    144:
                    145:        _IRC_GET_SENDER_OR_RETURN_(from, Req, Client)
                    146:
                    147:        /* Search user */
                    148:        target = Client_Search(Req->argv[0]);
                    149:        if (!target || (Client_Type(target) != CLIENT_USER))
                    150:                return IRC_WriteErrClient(from, ERR_NOSUCHNICK_MSG,
                    151:                                          Client_ID(Client), Req->argv[0]);
                    152:
                    153:        if (Req->argv[1][0] == '&') {
                    154:                /* Local channel. Make sure the target user is on this server! */
                    155:                if (Client_Conn(target) == NONE)
                    156:                        return IRC_WriteErrClient(from, ERR_USERNOTONSERV_MSG,
                    157:                                                  Client_ID(Client),
                    158:                                                  Req->argv[0]);
                    159:        }
                    160:
                    161:        chan = Channel_Search(Req->argv[1]);
                    162:        if (chan) {
                    163:                /* Channel exists. Is the user a valid member of the channel? */
                    164:                if (!Channel_IsMemberOf(chan, from))
                    165:                        return IRC_WriteErrClient(from, ERR_NOTONCHANNEL_MSG,
                    166:                                                  Client_ID(Client),
                    167:                                                  Req->argv[1]);
                    168:
                    169:                /* Is the channel "invite-disallow"? */
                    170:                if (Channel_HasMode(chan, 'V'))
                    171:                        return IRC_WriteErrClient(from, ERR_NOINVITE_MSG,
                    172:                                                  Client_ID(from),
                    173:                                                  Channel_Name(chan));
                    174:
                    175:                /* Is the channel "invite-only"? */
                    176:                if (Channel_HasMode(chan, 'i')) {
                    177:                        /* Yes. The user issuing the INVITE command must be
                    178:                         * channel owner/admin/operator/halfop! */
                    179:                        if (!Channel_UserHasMode(chan, from, 'q') &&
                    180:                            !Channel_UserHasMode(chan, from, 'a') &&
                    181:                            !Channel_UserHasMode(chan, from, 'o') &&
                    182:                            !Channel_UserHasMode(chan, from, 'h'))
                    183:                                return IRC_WriteErrClient(from,
                    184:                                                          ERR_CHANOPRIVSNEEDED_MSG,
                    185:                                                          Client_ID(from),
                    186:                                                          Channel_Name(chan));
                    187:                        remember = true;
                    188:                }
                    189:
                    190:                /* Is the target user already member of the channel? */
                    191:                if (Channel_IsMemberOf(chan, target))
                    192:                        return IRC_WriteErrClient(from, ERR_USERONCHANNEL_MSG,
                    193:                                                  Client_ID(from),
                    194:                                                  Req->argv[0], Req->argv[1]);
                    195:
                    196:                /* If the target user is banned on that channel: remember invite */
                    197:                if (Lists_Check(Channel_GetListBans(chan), target))
                    198:                        remember = true;
                    199:
                    200:                if (remember) {
                    201:                        /* We must remember this invite */
                    202:                        if (!Channel_AddInvite(chan, Client_MaskCloaked(target),
                    203:                                                true, Client_ID(from)))
                    204:                                return CONNECTED;
                    205:                }
                    206:        }
                    207:
                    208:        LogDebug("User \"%s\" invites \"%s\" to \"%s\" ...", Client_Mask(from),
                    209:                 Req->argv[0], Req->argv[1]);
                    210:
                    211:        /*
                    212:         * RFC 2812 states:
                    213:         * 'There is no requirement that the channel [..] must exist or be a
                    214:         * valid channel'. The problem with this is that this allows the
                    215:         * "channel" to contain spaces, in which case we must prefix its name
                    216:         * with a colon to make it clear that it is only a single argument.
                    217:         */
                    218:        colon_if_necessary = strchr(Req->argv[1], ' ') ? ":":"";
                    219:        /* Inform target client */
                    220:        IRC_WriteStrClientPrefix(target, from, "INVITE %s %s%s", Req->argv[0],
                    221:                                  colon_if_necessary, Req->argv[1]);
                    222:
                    223:        if (Client_Conn(target) > NONE) {
                    224:                /* The target user is local, so we have to send the status code */
                    225:                if (!IRC_WriteStrClientPrefix(from, target, RPL_INVITING_MSG,
                    226:                                               Client_ID(from), Req->argv[0],
                    227:                                               colon_if_necessary, Req->argv[1]))
                    228:                        return DISCONNECTED;
                    229:
                    230:                if (Client_HasMode(target, 'a') &&
                    231:                        !IRC_WriteStrClient(from, RPL_AWAY_MSG, Client_ID(from),
                    232:                                        Client_ID(target), Client_Away(target)))
                    233:                                return DISCONNECTED;
                    234:        }
                    235:        return CONNECTED;
                    236: } /* IRC_INVITE */
                    237:
                    238: /* -eof- */

CVSweb