]> arthur.barton.de Git - ngircd.git/commitdiff
Allow KICK to handle comma-delimited lists (of channels, nicks).
authorBryan Caldwell <bcaldwel@ucsd.edu>
Mon, 5 May 2008 14:04:48 +0000 (16:04 +0200)
committerFlorian Westphal <fw@strlen.de>
Mon, 5 May 2008 14:12:41 +0000 (16:12 +0200)
includes test cases.

[fw@strlen.de:
- move code around to avoid duplication
- use const where possible
- integrate test case]

ChangeLog
src/ngircd/irc-op.c
src/testsuite/Makefile.am
src/testsuite/kick-test.e [new file with mode: 0644]

index 921bbf6b5d7acac4d2cb1657b572483010201f97..490257eb20f2e456c8caa14fe7bd63a6f38db717 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -12,6 +12,8 @@
 
 ngIRCd-dev
 
+  - Fixed Bug 75: KICK now handles comma-delimited lists.
+    (Brandon Beresini, Bryan Caldwell)
   - Fixed Bug 83: ngIRCd chokes on 1-character messages.
   - Add support for modeless channels ("+channels").
     (Bryan Caldwell, Ali Shemiran)
index bbedcf4caf9968a4ecfbc7a8291660741a73d02a..715323be3ddd0f947079bdb879b494ca674ab3a4 100644 (file)
@@ -14,8 +14,6 @@
 
 #include "portab.h"
 
-static char UNUSED id[] = "$Id: irc-op.c,v 1.17 2006/12/07 17:57:20 fw Exp $";
-
 #include "imp.h"
 #include <assert.h>
 #include <string.h>
@@ -35,28 +33,96 @@ static char UNUSED id[] = "$Id: irc-op.c,v 1.17 2006/12/07 17:57:20 fw Exp $";
 #include "irc-op.h"
 
 
+static bool
+try_kick(CLIENT* from, const char *nick, const char *channel, const char *reason)
+{
+       CLIENT *target = Client_Search(nick);
+
+       if (!target)
+               return IRC_WriteStrClient(from, ERR_NOSUCHNICK_MSG, Client_ID(from), nick);
+
+       Channel_Kick(target, from, channel, reason);
+       return true;
+}
+
+
 GLOBAL bool
-IRC_KICK( CLIENT *Client, REQUEST *Req )
+IRC_KICK(CLIENT *Client, REQUEST *Req)
 {
-       CLIENT *target, *from;
-       
+       CLIENT *from;
+       char *itemList = Req->argv[0];
+       const char* currentNick, *currentChannel, *reason;
+       unsigned int channelCount = 1;
+       unsigned int nickCount = 1;
+
        assert( Client != NULL );
        assert( Req != NULL );
 
-       /* Falsche Anzahl Parameter? */
-       if(( Req->argc < 2) || ( Req->argc > 3 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+       if ((Req->argc < 2) || (Req->argc > 3))
+               return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
+                                       Client_ID(Client), Req->command);
+
+       while (*itemList) {
+               if (*itemList == ',') {
+                       *itemList = '\0';
+                       channelCount++;
+               }
+               itemList++;
+       }
 
-       if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix );
-       else from = Client;
-       if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
-       
-       /* Ziel-User suchen */
-       target = Client_Search( Req->argv[1] );
-       if( ! target ) return IRC_WriteStrClient( from, ERR_NOSUCHNICK_MSG, Client_ID( from ), Req->argv[1] );
+       itemList = Req->argv[1];
+       while (*itemList) {
+               if (*itemList == ',') {
+                       *itemList = '\0';
+                       nickCount++;
+               }
+               itemList++;
+       }
 
-       Channel_Kick( target, from, Req->argv[0], Req->argc == 3 ? Req->argv[2] : Client_ID( from ));
-       return CONNECTED;
-} /* IRC_KICK */       
+       if (Client_Type(Client) == CLIENT_SERVER)
+               from = Client_Search(Req->prefix);
+       else
+               from = Client;
+
+       if (!from)
+               return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
+                                       Client_ID(Client), Req->prefix);
+
+       reason = Req->argc == 3 ? Req->argv[2] : Client_ID(from);
+       currentNick = Req->argv[1];
+       currentChannel = Req->argv[0];
+       if (channelCount == 1) {
+               while (nickCount > 0) {
+                       if (!try_kick(from, currentNick, currentChannel, reason))
+                               return false;
+
+                       while (*currentNick)
+                               currentNick++;
+
+                       currentNick++;
+                       nickCount--;
+               }
+       } else if (channelCount == nickCount) {
+               while (nickCount > 0) {
+                       if (!try_kick(from, currentNick, currentChannel, reason))
+                               return false;
+
+                       while (*currentNick)
+                               currentNick++;
+
+                       while (*currentChannel)
+                               currentChannel++;
+
+                       currentNick++;
+                       currentChannel++;
+                       nickCount--;
+               }
+       } else {
+               return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
+                                       Client_ID(Client), Req->command);
+       }
+       return true;
+} /* IRC_KICK */
 
 
 GLOBAL bool
index bc8df8442deb534d61a6f4f25ad3c21397249904..af1d980bc289b8a55276f220570f37b02fc1848f 100644 (file)
@@ -21,6 +21,7 @@ EXTRA_DIST = \
        start-server.sh stop-server.sh tests.sh stress-server.sh \
        test-loop.sh wait-tests.sh \
        channel-test.e connect-test.e check-idle.e misc-test.e mode-test.e \
+       kick-test.e \
        opless-channel-test.e \
        who-test.e stress-A.e stress-B.e \
        ngircd-test.conf
@@ -48,6 +49,10 @@ channel-test: tests.sh
        rm -f channel-test
        ln -s $(srcdir)/tests.sh channel-test
 
+kick-test: tests.sh
+       rm -f kick-test
+       ln -s $(srcdir)/tests.sh kick-test
+
 opless-channel-test: tests.sh
        rm -f opless-channel-test
        ln -s $(srcdir)/tests.sh opless-channel-test
@@ -67,6 +72,7 @@ mode-test: tests.sh
 TESTS = start-server.sh \
        connect-test \
        channel-test \
+       kick-test \
        misc-test \
        mode-test \
        who-test \
diff --git a/src/testsuite/kick-test.e b/src/testsuite/kick-test.e
new file mode 100644 (file)
index 0000000..9412d32
--- /dev/null
@@ -0,0 +1,112 @@
+spawn telnet localhost 6789
+expect {
+       timeout { exit 1 }
+       "Connected"
+}
+
+send "nick nick\r"
+send "user user . . :User\r"
+expect {
+       timeout { exit 1 }
+       "376"
+}
+
+send "kick #Channel nick\r"
+expect {
+       timeout { exit 1 }
+       "403"
+}
+
+send "join #Channel\r"
+
+send "kick #Channel nick\r"
+expect {
+       timeout { exit 1 }
+       "@* KICK #Channel nick :nick"
+}
+
+send "join #Channel\r"
+
+send "kick #Channel nick :reason\r"
+expect {
+       timeout { exit 1 }
+       "@* KICK #Channel nick :reason"
+}
+
+send "join #Channel,#Channel2\r"
+
+send "kick #Channel,#Channel2 nick\r"
+expect {
+       timeout { exit 1 }
+       "461"
+}
+
+send "kick #Channel,#Channel2,#NoExists,#NoExists nick1,nick,nick3,nick :reason\r"
+expect {
+       timeout { exit 1 }
+       "401"
+}
+expect {
+       timeout { exit 1 }
+       "@* KICK #Channel2 nick :reason"
+}
+expect {
+       timeout { exit 1 }
+       "401"
+}
+expect {
+       timeout { exit 1 }
+       "403"
+}
+
+send "kick #Channel nick2,nick,nick3\r"
+expect {
+       timeout { exit 1 }
+       "401"
+}
+expect {
+       timeout { exit 1 }
+       "@* KICK #Channel nick :nick"
+}
+expect {
+       timeout { exit 1 }
+       "401"
+}
+
+send "kick #Channel ,,\r"
+expect {
+       timeout { exit 1 }
+       "401"
+}
+expect {
+       timeout { exit 1 }
+       "401"
+}
+
+send "kick ,, ,,,\r"
+expect {
+       timeout { exit 1 }
+       "461"
+}
+
+send "kick ,, ,,\r"
+expect {
+       timeout { exit 1 }
+       "401"
+}
+expect {
+       timeout { exit 1 }
+       "401"
+}
+expect {
+       timeout { exit 1 }
+       "401"
+}
+
+send "quit\r"
+expect {
+       timeout { exit 1 }
+       "Connection closed"
+}
+
+# -eof-