]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_hideoper.cpp
64872850a5c31ab19dde6354a17659181f7d75fb
[user/henk/code/inspircd.git] / src / modules / m_hideoper.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2019 linuxdaemon <linuxdaemon.irc@gmail.com>
5  *   Copyright (C) 2014 Adam <Adam@anope.org>
6  *   Copyright (C) 2013, 2015, 2017-2018 Sadie Powell <sadie@witchery.services>
7  *   Copyright (C) 2012-2016 Attila Molnar <attilamolnar@hush.com>
8  *   Copyright (C) 2012 Robby <robby@chatbelgie.be>
9  *   Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
10  *   Copyright (C) 2008 Robin Burchell <robin+git@viroteck.net>
11  *   Copyright (C) 2008 Geoff Bricker <geoff.bricker@gmail.com>
12  *   Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
13  *   Copyright (C) 2006, 2010 Craig Edwards <brain@inspircd.org>
14  *
15  * This file is part of InspIRCd.  InspIRCd is free software: you can
16  * redistribute it and/or modify it under the terms of the GNU General Public
17  * License as published by the Free Software Foundation, version 2.
18  *
19  * This program is distributed in the hope that it will be useful, but WITHOUT
20  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
21  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
22  * details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
26  */
27
28
29 #include "inspircd.h"
30 #include "modules/stats.h"
31 #include "modules/who.h"
32 #include "modules/whois.h"
33
34 /** Handles user mode +H
35  */
36 class HideOper : public SimpleUserModeHandler
37 {
38  public:
39         size_t opercount;
40
41         HideOper(Module* Creator) : SimpleUserModeHandler(Creator, "hideoper", 'H')
42                 , opercount(0)
43         {
44                 oper = true;
45         }
46
47         ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string& parameter, bool adding) CXX11_OVERRIDE
48         {
49                 if (SimpleUserModeHandler::OnModeChange(source, dest, channel, parameter, adding) == MODEACTION_DENY)
50                         return MODEACTION_DENY;
51
52                 if (adding)
53                         opercount++;
54                 else
55                         opercount--;
56
57                 return MODEACTION_ALLOW;
58         }
59 };
60
61 class ModuleHideOper
62         : public Module
63         , public Stats::EventListener
64         , public Who::EventListener
65         , public Whois::LineEventListener
66 {
67  private:
68         HideOper hm;
69         bool active;
70
71  public:
72         ModuleHideOper()
73                 : Stats::EventListener(this)
74                 , Who::EventListener(this)
75                 , Whois::LineEventListener(this)
76                 , hm(this)
77                 , active(false)
78         {
79         }
80
81         Version GetVersion() CXX11_OVERRIDE
82         {
83                 return Version("Adds user mode H (hideoper) which hides the server operator status of a user from unprivileged users.", VF_VENDOR);
84         }
85
86         void OnUserQuit(User* user, const std::string&, const std::string&) CXX11_OVERRIDE
87         {
88                 if (user->IsModeSet(hm))
89                         hm.opercount--;
90         }
91
92         ModResult OnNumeric(User* user, const Numeric::Numeric& numeric) CXX11_OVERRIDE
93         {
94                 if (numeric.GetNumeric() != RPL_LUSEROP || active || user->HasPrivPermission("users/auspex"))
95                         return MOD_RES_PASSTHRU;
96
97                 // If there are no visible operators then we shouldn't send the numeric.
98                 size_t opercount = ServerInstance->Users->all_opers.size() - hm.opercount;
99                 if (opercount)
100                 {
101                         active = true;
102                         user->WriteNumeric(RPL_LUSEROP, opercount, "operator(s) online");
103                         active = false;
104                 }
105                 return MOD_RES_DENY;
106         }
107
108         ModResult OnWhoisLine(Whois::Context& whois, Numeric::Numeric& numeric) CXX11_OVERRIDE
109         {
110                 /* Dont display numeric 313 (RPL_WHOISOPER) if they have +H set and the
111                  * person doing the WHOIS is not an oper
112                  */
113                 if (numeric.GetNumeric() != 313)
114                         return MOD_RES_PASSTHRU;
115
116                 if (!whois.GetTarget()->IsModeSet(hm))
117                         return MOD_RES_PASSTHRU;
118
119                 if (!whois.GetSource()->HasPrivPermission("users/auspex"))
120                         return MOD_RES_DENY;
121
122                 return MOD_RES_PASSTHRU;
123         }
124
125         ModResult OnWhoLine(const Who::Request& request, LocalUser* source, User* user, Membership* memb, Numeric::Numeric& numeric) CXX11_OVERRIDE
126         {
127                 if (user->IsModeSet(hm) && !source->HasPrivPermission("users/auspex"))
128                 {
129                         // Hide the line completely if doing a "/who * o" query
130                         if (request.flags['o'])
131                                 return MOD_RES_DENY;
132
133                         size_t flag_index;
134                         if (!request.GetFieldIndex('f', flag_index))
135                                 return MOD_RES_PASSTHRU;
136
137                         // hide the "*" that marks the user as an oper from the /WHO line
138                         // #chan ident localhost insp22.test nick H@ :0 Attila
139                         if (numeric.GetParams().size() <= flag_index)
140                                 return MOD_RES_PASSTHRU;
141
142                         std::string& param = numeric.GetParams()[flag_index];
143                         const std::string::size_type pos = param.find('*');
144                         if (pos != std::string::npos)
145                                 param.erase(pos, 1);
146                 }
147                 return MOD_RES_PASSTHRU;
148         }
149
150         ModResult OnStats(Stats::Context& stats) CXX11_OVERRIDE
151         {
152                 if (stats.GetSymbol() != 'P')
153                         return MOD_RES_PASSTHRU;
154
155                 unsigned int count = 0;
156                 const UserManager::OperList& opers = ServerInstance->Users->all_opers;
157                 for (UserManager::OperList::const_iterator i = opers.begin(); i != opers.end(); ++i)
158                 {
159                         User* oper = *i;
160                         if (!oper->server->IsULine() && (stats.GetSource()->IsOper() || !oper->IsModeSet(hm)))
161                         {
162                                 LocalUser* lu = IS_LOCAL(oper);
163                                 const std::string idle = lu ? InspIRCd::DurationString(ServerInstance->Time() - lu->idle_lastmsg) : "unavailable";
164                                 stats.AddRow(249, InspIRCd::Format("%s (%s@%s) Idle: %s", oper->nick.c_str(),
165                                         oper->ident.c_str(), oper->GetDisplayedHost().c_str(), idle.c_str()));
166                                 count++;
167                         }
168                 }
169                 stats.AddRow(249, ConvToStr(count)+" OPER(s)");
170
171                 return MOD_RES_DENY;
172         }
173 };
174
175 MODULE_INIT(ModuleHideOper)