1 /*
2 * InspIRCd -- Internet Relay Chat Daemon
3 *
4 * Copyright (C) 2013, 2017 Sadie Powell <sadie@witchery.services>
5 * Copyright (C) 2012-2016 Attila Molnar <attilamolnar@hush.com>
6 * Copyright (C) 2012, 2019 Robby <robby@chatbelgie.be>
7 * Copyright (C) 2009-2010 Craig Edwards <brain@inspircd.org>
8 * Copyright (C) 2009 Uli Schlachter <psychon@inspircd.org>
9 * Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
10 * Copyright (C) 2008 Robin Burchell <robin+git@viroteck.net>
11 *
12 * This file is part of InspIRCd. InspIRCd is free software: you can
13 * redistribute it and/or modify it under the terms of the GNU General Public
14 * License as published by the Free Software Foundation, version 2.
15 *
16 * This program is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
19 * details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 */
24
25
26 /*
27 * Originally by Chernov-Phoenix Alexey (Phoenix@RusNet) mailto:phoenix /email address separator/ pravmail.ru
28 */
29
30 #include "inspircd.h"
31
32 #define OPERPREFIX_VALUE 1000000
33
34 class OperPrefixMode : public PrefixMode
35 {
36 public:
OperPrefixMode(Module * Creator)37 OperPrefixMode(Module* Creator)
38 : PrefixMode(Creator, "operprefix", 'y', OPERPREFIX_VALUE)
39 {
40 prefix = ServerInstance->Config->ConfValue("operprefix")->getString("prefix", "!", 1, 1)[0];
41 ranktoset = ranktounset = UINT_MAX;
42 }
43 };
44
45 class ModuleOperPrefixMode;
46 class HideOperWatcher : public ModeWatcher
47 {
48 ModuleOperPrefixMode* parentmod;
49
50 public:
51 HideOperWatcher(ModuleOperPrefixMode* parent);
52 void AfterMode(User* source, User* dest, Channel* channel, const std::string ¶meter, bool adding) CXX11_OVERRIDE;
53 };
54
55 class ModuleOperPrefixMode : public Module
56 {
57 OperPrefixMode opm;
58 HideOperWatcher hideoperwatcher;
59 UserModeReference hideopermode;
60
61 public:
ModuleOperPrefixMode()62 ModuleOperPrefixMode()
63 : opm(this), hideoperwatcher(this)
64 , hideopermode(this, "hideoper")
65 {
66 /* To give clients a chance to learn about the new prefix we don't give +y to opers
67 * right now. That means if the module was loaded after opers have joined channels
68 * they need to rejoin them in order to get the oper prefix.
69 */
70 }
71
OnUserPreJoin(LocalUser * user,Channel * chan,const std::string & cname,std::string & privs,const std::string & keygiven)72 ModResult OnUserPreJoin(LocalUser* user, Channel* chan, const std::string& cname, std::string& privs, const std::string& keygiven) CXX11_OVERRIDE
73 {
74 if ((user->IsOper()) && (!user->IsModeSet(hideopermode)))
75 privs.push_back('y');
76 return MOD_RES_PASSTHRU;
77 }
78
OnPostJoin(Membership * memb)79 void OnPostJoin(Membership* memb) CXX11_OVERRIDE
80 {
81 if ((!IS_LOCAL(memb->user)) || (!memb->user->IsOper()) || (memb->user->IsModeSet(hideopermode)))
82 return;
83
84 if (memb->HasMode(&opm))
85 return;
86
87 // The user was force joined and OnUserPreJoin() did not run. Set the operprefix now.
88 Modes::ChangeList changelist;
89 changelist.push_add(&opm, memb->user->nick);
90 ServerInstance->Modes.Process(ServerInstance->FakeClient, memb->chan, NULL, changelist);
91 }
92
SetOperPrefix(User * user,bool add)93 void SetOperPrefix(User* user, bool add)
94 {
95 Modes::ChangeList changelist;
96 changelist.push(&opm, add, user->nick);
97 for (User::ChanList::iterator v = user->chans.begin(); v != user->chans.end(); v++)
98 ServerInstance->Modes->Process(ServerInstance->FakeClient, (*v)->chan, NULL, changelist);
99 }
100
OnPostOper(User * user,const std::string & opername,const std::string & opertype)101 void OnPostOper(User* user, const std::string& opername, const std::string& opertype) CXX11_OVERRIDE
102 {
103 if (IS_LOCAL(user) && (!user->IsModeSet(hideopermode)))
104 SetOperPrefix(user, true);
105 }
106
GetVersion()107 Version GetVersion() CXX11_OVERRIDE
108 {
109 return Version("Adds the server operator-only y (operprefix) channel prefix mode.", VF_VENDOR);
110 }
111
Prioritize()112 void Prioritize() CXX11_OVERRIDE
113 {
114 // m_opermodes may set +H on the oper to hide him, we don't want to set the oper prefix in that case
115 Module* opermodes = ServerInstance->Modules->Find("m_opermodes.so");
116 ServerInstance->Modules->SetPriority(this, I_OnPostOper, PRIORITY_AFTER, opermodes);
117 }
118 };
119
HideOperWatcher(ModuleOperPrefixMode * parent)120 HideOperWatcher::HideOperWatcher(ModuleOperPrefixMode* parent)
121 : ModeWatcher(parent, "hideoper", MODETYPE_USER)
122 , parentmod(parent)
123 {
124 }
125
AfterMode(User * source,User * dest,Channel * channel,const std::string & parameter,bool adding)126 void HideOperWatcher::AfterMode(User* source, User* dest, Channel* channel, const std::string& parameter, bool adding)
127 {
128 // If hideoper is being unset because the user is deopering, don't set +y
129 if (IS_LOCAL(dest) && dest->IsOper())
130 parentmod->SetOperPrefix(dest, !adding);
131 }
132
133 MODULE_INIT(ModuleOperPrefixMode)
134