- if( ok && (( ! only_ops ) || ( strchr( Client_Modes( c ), 'o' ))))
- {
- /* Flags zusammenbasteln */
- strcpy( flags, "H" );
- if( strchr( Client_Modes( c ), 'o' )) strlcat( flags, "*", sizeof( flags ));
-
- /* ausgeben */
- cl2chan = Channel_FirstChannelOf( c );
- if( cl2chan ) ptr = Channel_Name( Channel_GetChannel( cl2chan ));
- else ptr = "*";
- if( ! IRC_WriteStrClient( Client, RPL_WHOREPLY_MSG, Client_ID( Client ), ptr, Client_User( c ), Client_Hostname( c ), Client_ID( Client_Introducer( c )), Client_ID( c ), flags, Client_Hops( c ), Client_Info( c ))) return DISCONNECTED;
+ return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, Client_ID(Client),
+ Channel_Name(Chan));
+}
+
+
+/**
+ * Send WHO reply for a "mask target" ("WHO m*sk").
+ *
+ * @param Client Client requesting the information.
+ * @param Mask Mask being requested or NULL for "all" clients.
+ * @param OnlyOps Only display IRC operators.
+ * @return CONNECTED or DISCONNECTED.
+ */
+static bool
+IRC_WHO_Mask(CLIENT *Client, char *Mask, bool OnlyOps)
+{
+ CLIENT *c;
+ CL2CHAN *cl2chan;
+ CHANNEL *chan;
+ bool client_match, is_visible;
+ char flags[4];
+ int count = 0;
+
+ assert (Client != NULL);
+
+ if (Mask)
+ ngt_LowerStr(Mask);
+
+ IRC_SetPenalty(Client, 3);
+ for (c = Client_First(); c != NULL; c = Client_Next(c)) {
+ if (Client_Type(c) != CLIENT_USER)
+ continue;
+
+ if (OnlyOps && !Client_HasMode(c, 'o'))
+ continue;
+
+ if (Mask) {
+ /* Match pattern against user host/server/name/nick */
+ client_match = MatchCaseInsensitive(Mask,
+ Client_Hostname(c));
+ if (!client_match)
+ client_match = MatchCaseInsensitive(Mask,
+ Client_ID(Client_Introducer(c)));
+ if (!client_match)
+ client_match = MatchCaseInsensitive(Mask,
+ Client_Info(c));
+ if (!client_match)
+ client_match = MatchCaseInsensitive(Mask,
+ Client_ID(c));
+ if (!client_match)
+ continue; /* no match: skip this client */
+ }
+
+ is_visible = !Client_HasMode(c, 'i');
+
+ /* Target client is invisible, but mask matches exactly? */
+ if (!is_visible && Mask && strcasecmp(Client_ID(c), Mask) == 0)
+ is_visible = true;
+
+ /* Target still invisible, but are both on the same channel? */
+ if (!is_visible) {
+ cl2chan = Channel_FirstChannelOf(Client);
+ while (cl2chan && !is_visible) {
+ chan = Channel_GetChannel(cl2chan);
+ if (Channel_IsMemberOf(chan, c))
+ is_visible = true;
+ cl2chan = Channel_NextChannelOf(Client, cl2chan);