]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/coremods/core_who.cpp
Add support for blocking tag messages with the deaf mode.
[user/henk/code/inspircd.git] / src / coremods / core_who.cpp
index 362e79c03c8e540df8170e0609d9f616790c0c20..aa19efe97db3f156ce432fa394750e3911c03818 100644 (file)
@@ -1,10 +1,16 @@
 /*
  * InspIRCd -- Internet Relay Chat Daemon
  *
- *   Copyright (C) 2018 Peter Powell <petpow@saberuk.com>
- *   Copyright (C) 2014 Adam <Adam@anope.org>
+ *   Copyright (C) 2019 linuxdaemon <linuxdaemon.irc@gmail.com>
+ *   Copyright (C) 2018 Adam <Adam@anope.org>
+ *   Copyright (C) 2017-2019, 2021 Sadie Powell <sadie@witchery.services>
+ *   Copyright (C) 2013-2014, 2016 Attila Molnar <attilamolnar@hush.com>
+ *   Copyright (C) 2012, 2019 Robby <robby@chatbelgie.be>
  *   Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
- *   Copyright (C) 2007-2008 Robin Burchell <robin+git@viroteck.net>
+ *   Copyright (C) 2009 John Brooks <special@inspircd.org>
+ *   Copyright (C) 2008 Robin Burchell <robin+git@viroteck.net>
+ *   Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
+ *   Copyright (C) 2006-2008, 2010 Craig Edwards <brain@inspircd.org>
  *
  * This file is part of InspIRCd.  InspIRCd is free software: you can
  * redistribute it and/or modify it under the terms of the GNU General Public
@@ -22,6 +28,7 @@
 
 #include "inspircd.h"
 #include "modules/account.h"
+#include "modules/who.h"
 
 enum
 {
@@ -33,40 +40,43 @@ enum
        RPL_WHOSPCRPL = 354
 };
 
-struct WhoData
-{
-       // The flags for matching users to include.
-       std::bitset<UCHAR_MAX> flags;
-
-       // Whether we are matching using a wildcard or a flag.
-       bool fuzzy_match;
+static const char whox_field_order[] = "tcuihsnfdlaor";
+static const char who_field_order[] = "cuhsnf";
 
-       // The text to match against.
-       std::string matchtext;
+struct WhoData : public Who::Request
+{
+       bool GetFieldIndex(char flag, size_t& out) const CXX11_OVERRIDE
+       {
+               if (!whox)
+               {
+                       const char* pos = strchr(who_field_order, flag);
+                       if (pos == NULL)
+                               return false;
 
-       // The WHO/WHOX responses we will send to the source.
-       std::vector<Numeric::Numeric> results;
+                       out = pos - who_field_order;
+                       return true;
+               }
 
-       // Whether the source requested a WHOX response.
-       bool whox;
+               if (!whox_fields[flag])
+                       return false;
 
-       // The fields to include in the WHOX response.
-       std::bitset<UCHAR_MAX> whox_fields;
+               out = 0;
+               for (const char* c = whox_field_order; *c && *c != flag; ++c)
+               {
+                       if (whox_fields[*c])
+                               ++out;
+               }
 
-       // A user specified label for the WHOX response.
-       std::string whox_querytype;
+               return whox_field_order[out];
+       }
 
        WhoData(const CommandBase::Params& parameters)
-               : whox(false)
        {
                // Find the matchtext and swap the 0 for a * so we can use InspIRCd::Match on it.
                matchtext = parameters.size() > 2 ? parameters[2] : parameters[0];
                if (matchtext == "0")
                        matchtext = "*";
 
-               // Fuzzy matches are when the source has not specified a specific user.
-               fuzzy_match = (parameters.size() > 1) || (matchtext.find_first_of("*?.") != std::string::npos);
-
                // If flags have been specified by the source.
                if (parameters.size() > 1)
                {
@@ -95,6 +105,9 @@ struct WhoData
                                current_bitset->set(chr);
                        }
                }
+
+               // Fuzzy matches are when the source has not specified a specific user.
+               fuzzy_match = flags.any() || (matchtext.find_first_of("*?.") != std::string::npos);
        }
 };
 
@@ -105,6 +118,7 @@ class CommandWho : public SplitCommand
        ChanModeReference privatemode;
        UserModeReference hidechansmode;
        UserModeReference invisiblemode;
+       Events::ModuleEventProvider whoevprov;
 
        /** Determines whether a user can view the users of a channel. */
        bool CanView(Channel* chan, User* user)
@@ -137,7 +151,7 @@ class CommandWho : public SplitCommand
        }
 
        /** Determines whether WHO flags match a specific channel user. */
-       static bool MatchChannel(LocalUser* source, Membership* memb, WhoData& data);
+       bool MatchChannel(LocalUser* source, Membership* memb, WhoData& data);
 
        /** Determines whether WHO flags match a specific user. */
        static bool MatchUser(LocalUser* source, User* target, WhoData& data);
@@ -160,9 +174,10 @@ class CommandWho : public SplitCommand
                , privatemode(parent, "private")
                , hidechansmode(parent, "hidechans")
                , invisiblemode(parent, "invisible")
+               , whoevprov(parent, "event/who")
        {
                allow_empty_last_param = false;
-               syntax = "<server>|<nickname>|<channel>|<realname>|<host>|0 [[Aafhilmnoprstu] <server>|<nickname>|<channel>|<realname>|<host>|0]";
+               syntax = "<server>|<nick>|<channel>|<realname>|<host>|0 [[Aafhilmnoprstux][%acdfhilnorstu] <server>|<nick>|<channel>|<realname>|<host>|0]";
        }
 
        /** Sends a WHO reply to a user. */
@@ -293,7 +308,7 @@ bool CommandWho::MatchUser(LocalUser* source, User* user, WhoData& data)
                        long port;
                        while ((port = portrange.GetToken()))
                        {
-                               if (port == lu->GetServerPort())
+                               if (port == lu->server_sa.port())
                                {
                                        match = true;
                                        break;
@@ -376,13 +391,14 @@ void CommandWho::WhoChannel(LocalUser* source, const std::vector<std::string>& p
 template<typename T>
 void CommandWho::WhoUsers(LocalUser* source, const std::vector<std::string>& parameters, const T& users, WhoData& data)
 {
+       bool source_has_users_auspex = source->HasPrivPermission("users/auspex");
        for (typename T::const_iterator iter = users.begin(); iter != users.end(); ++iter)
        {
                User* user = GetUser(iter);
 
                // Only show users in response to a fuzzy WHO if we can see them normally.
                bool can_see_normally = user == source || source->SharesChannelWith(user) || !user->IsModeSet(invisiblemode);
-               if (data.fuzzy_match && !can_see_normally && !source->HasPrivPermission("users/auspex"))
+               if (data.fuzzy_match && !can_see_normally && !source_has_users_auspex)
                        continue;
 
                // Skip the user if it doesn't match the query.
@@ -534,7 +550,7 @@ void CommandWho::SendWhoLine(LocalUser* source, const std::vector<std::string>&
        }
 
        ModResult res;
-       FIRST_MOD_RESULT(OnSendWhoLine, res, (source, parameters, user, memb, wholine));
+       FIRST_MOD_RESULT_CUSTOM(whoevprov, Who::EventListener, OnWhoLine, res, (data, source, user, memb, wholine));
        if (res != MOD_RES_DENY)
                data.results.push_back(wholine);
 }