Merge pull request #197 from LucentW/master
authorAlexander Barton <alex@barton.de>
Thu, 30 Apr 2015 07:28:15 +0000 (09:28 +0200)
committerAlexander Barton <alex@barton.de>
Thu, 30 Apr 2015 07:28:15 +0000 (09:28 +0200)
Implement user mode "I": Hide channels on WHOIS

User mode +I prevents ngIRCd from showing channels on WHOIS.
IRC Operators can always see those.

Closes #197.

doc/Modes.txt
src/ngircd/defines.h
src/ngircd/irc-info.c
src/ngircd/irc-mode.c

index a931787..61d5e8f 100644 (file)
@@ -2,7 +2,7 @@
                      ngIRCd - Next Generation IRC Server
                            http://ngircd.barton.de/
 
-               (c)2001-2014 Alexander Barton and Contributors.
+               (c)2001-2015 Alexander Barton and Contributors.
                ngIRCd is free software and published under the
                    terms of the GNU General Public License.
 
@@ -28,6 +28,7 @@ channels he is using at the moment.
   C    19      Only users that share a channel are allowed to send messages.
   F    22      Relaxed flood protection (only settable by IRC Operators).
   i    0.0.1   User is "invisible".
+  I 23 No channels are shown on WHOIS (IRC Operators can always see those).
   o    0.0.1   User is IRC operator.
   q    20      User is protected, can not be kicked from a channel.
   r    0.0.1   User is restricted.
index 456c4c9..ff849bb 100644 (file)
 #endif
 
 /** Supported user modes. */
-#define USERMODES "abBcCFioqrRswx"
+#define USERMODES "abBcCFiIoqrRswx"
 
 /** Supported channel modes. */
 #define CHANMODES "abehiIklmMnoOPqQrRstvVz"
index 61c6239..ba7a2b7 100644 (file)
@@ -313,48 +313,50 @@ IRC_WHOIS_SendReply(CLIENT *Client, CLIENT *from, CLIENT *c)
                                Client_Info(Client_Introducer(c))))
                return DISCONNECTED;
 
-       /* Channels */
-       snprintf(str, sizeof(str), RPL_WHOISCHANNELS_MSG,
-                Client_ID(from), Client_ID(c));
-       cl2chan = Channel_FirstChannelOf(c);
-       while (cl2chan) {
-               chan = Channel_GetChannel(cl2chan);
-               assert(chan != NULL);
-
-               /* next */
-               cl2chan = Channel_NextChannelOf(c, cl2chan);
-
-               /* Secret channel? */
-               if (Channel_HasMode(chan, 's')
-                   && !Channel_IsMemberOf(chan, Client))
-                       continue;
+       /* Channels, show only if client has no +I or if from is oper */
+       if(!(Client_HasMode(c, 'I')) || Client_HasMode(from, 'o'))  {
+               snprintf(str, sizeof(str), RPL_WHOISCHANNELS_MSG,
+                        Client_ID(from), Client_ID(c));
+               cl2chan = Channel_FirstChannelOf(c);
+               while (cl2chan) {
+                       chan = Channel_GetChannel(cl2chan);
+                       assert(chan != NULL);
+
+                       /* next */
+                       cl2chan = Channel_NextChannelOf(c, cl2chan);
+
+                       /* Secret channel? */
+                       if (Channel_HasMode(chan, 's')
+                           && !Channel_IsMemberOf(chan, Client))
+                               continue;
 
-               /* Local channel and request is not from a user? */
-               if (Client_Type(Client) == CLIENT_SERVER
-                   && Channel_IsLocal(chan))
-                       continue;
+                       /* Local channel and request is not from a user? */
+                       if (Client_Type(Client) == CLIENT_SERVER
+                           && Channel_IsLocal(chan))
+                               continue;
 
-               /* Concatenate channel names */
-               if (str[strlen(str) - 1] != ':')
-                       strlcat(str, " ", sizeof(str));
+                       /* Concatenate channel names */
+                       if (str[strlen(str) - 1] != ':')
+                               strlcat(str, " ", sizeof(str));
 
-               who_flags_qualifier(Client, Channel_UserModes(chan, c),
-                                   str, sizeof(str));
-               strlcat(str, Channel_Name(chan), sizeof(str));
+                       who_flags_qualifier(Client, Channel_UserModes(chan, c),
+                                           str, sizeof(str));
+                       strlcat(str, Channel_Name(chan), sizeof(str));
 
-               if (strlen(str) > (COMMAND_LEN - CHANNEL_NAME_LEN - 4)) {
-                       /* Line becomes too long: send it! */
+                       if (strlen(str) > (COMMAND_LEN - CHANNEL_NAME_LEN - 4)) {
+                               /* Line becomes too long: send it! */
+                               if (!IRC_WriteStrClient(Client, "%s", str))
+                                       return DISCONNECTED;
+                               snprintf(str, sizeof(str), RPL_WHOISCHANNELS_MSG,
+                                        Client_ID(from), Client_ID(c));
+                       }
+               }
+               if(str[strlen(str) - 1] != ':') {
+                       /* There is data left to send: */
                        if (!IRC_WriteStrClient(Client, "%s", str))
                                return DISCONNECTED;
-                       snprintf(str, sizeof(str), RPL_WHOISCHANNELS_MSG,
-                                Client_ID(from), Client_ID(c));
                }
        }
-       if(str[strlen(str) - 1] != ':') {
-               /* There is data left to send: */
-               if (!IRC_WriteStrClient(Client, "%s", str))
-                       return DISCONNECTED;
-       }
 
        /* IRC-Services? */
        if (Client_Type(c) == CLIENT_SERVICE &&
index cde573b..ec7d53c 100644 (file)
@@ -206,6 +206,7 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )
                case 'b': /* Block private msgs */
                case 'C': /* Only messages from clients sharing a channel */
                case 'i': /* Invisible */
+               case 'I': /* Hide channel list from WHOIS */
                case 's': /* Server messages */
                case 'w': /* Wallops messages */
                        x[0] = *mode_ptr;