]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_ojoin.cpp
Send ERR_BADCHANMASK when trying to OJOIN/SAJOIN an invalid channel.
[user/henk/code/inspircd.git] / src / modules / m_ojoin.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2019 Robby <robby@chatbelgie.be>
5  *   Copyright (C) 2013, 2017-2018, 2020 Sadie Powell <sadie@witchery.services>
6  *   Copyright (C) 2012-2014, 2016 Attila Molnar <attilamolnar@hush.com>
7  *   Copyright (C) 2010 Craig Edwards <brain@inspircd.org>
8  *   Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
9  *
10  * This file is part of InspIRCd.  InspIRCd is free software: you can
11  * redistribute it and/or modify it under the terms of the GNU General Public
12  * License as published by the Free Software Foundation, version 2.
13  *
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
17  * details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  */
22
23 #include "inspircd.h"
24
25 #define NETWORK_VALUE 9000000
26
27 /** Handle /OJOIN
28  */
29 class CommandOjoin : public SplitCommand
30 {
31  public:
32         bool active;
33         bool notice;
34         bool op;
35         ModeHandler* npmh;
36         ChanModeReference opmode;
37         CommandOjoin(Module* parent, ModeHandler& mode)
38                 : SplitCommand(parent, "OJOIN", 1)
39                 , npmh(&mode)
40                 , opmode(parent, "op")
41         {
42                 flags_needed = 'o';
43                 syntax = "<channel>";
44                 active = false;
45         }
46
47         CmdResult HandleLocal(LocalUser* user, const Params& parameters) CXX11_OVERRIDE
48         {
49                 // Make sure the channel name is allowable.
50                 if (!ServerInstance->IsChannel(parameters[0]))
51                 {
52                         user->WriteNumeric(ERR_BADCHANMASK, parameters[0], "Invalid channel name");
53                         return CMD_FAILURE;
54                 }
55
56                 active = true;
57                 // override is false because we want OnUserPreJoin to run
58                 Channel* channel = Channel::JoinUser(user, parameters[0], false);
59                 active = false;
60
61                 if (channel)
62                 {
63                         ServerInstance->SNO->WriteGlobalSno('a', user->nick+" used OJOIN to join "+channel->name);
64
65                         if (notice)
66                                 channel->WriteRemoteNotice(user->nick + " joined on official network business.");
67                 }
68                 else
69                 {
70                         channel = ServerInstance->FindChan(parameters[0]);
71                         if (!channel)
72                                 return CMD_FAILURE;
73
74                         ServerInstance->SNO->WriteGlobalSno('a', user->nick+" used OJOIN in "+parameters[0]);
75                         // they're already in the channel
76                         Modes::ChangeList changelist;
77                         changelist.push_add(npmh, user->nick);
78                         if (op && opmode)
79                                 changelist.push_add(*opmode, user->nick);
80                         ServerInstance->Modes->Process(ServerInstance->FakeClient, channel, NULL, changelist);
81                 }
82                 return CMD_SUCCESS;
83         }
84 };
85
86 /** channel mode +Y
87  */
88 class NetworkPrefix : public PrefixMode
89 {
90  public:
91         NetworkPrefix(Module* parent, char NPrefix)
92                 : PrefixMode(parent, "official-join", 'Y', NETWORK_VALUE, NPrefix)
93         {
94                 ranktoset = ranktounset = UINT_MAX;
95         }
96
97         ModResult AccessCheck(User* source, Channel* channel, std::string &parameter, bool adding) CXX11_OVERRIDE
98         {
99                 User* theuser = ServerInstance->FindNick(parameter);
100                 // remove own privs?
101                 if (source == theuser && !adding)
102                         return MOD_RES_ALLOW;
103
104                 return MOD_RES_PASSTHRU;
105         }
106 };
107
108 class ModuleOjoin : public Module
109 {
110         NetworkPrefix np;
111         CommandOjoin mycommand;
112
113  public:
114
115         ModuleOjoin()
116                 : np(this, ServerInstance->Config->ConfValue("ojoin")->getString("prefix").c_str()[0])
117                 , mycommand(this, np)
118         {
119         }
120
121         ModResult OnUserPreJoin(LocalUser* user, Channel* chan, const std::string& cname, std::string& privs, const std::string& keygiven) CXX11_OVERRIDE
122         {
123                 if (mycommand.active)
124                 {
125                         privs += np.GetModeChar();
126                         if (mycommand.op && mycommand.opmode)
127                                 privs += mycommand.opmode->IsPrefixMode()->GetPrefix();
128                         return MOD_RES_ALLOW;
129                 }
130
131                 return MOD_RES_PASSTHRU;
132         }
133
134         void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
135         {
136                 ConfigTag* Conf = ServerInstance->Config->ConfValue("ojoin");
137                 mycommand.notice = Conf->getBool("notice", true);
138                 mycommand.op = Conf->getBool("op", true);
139         }
140
141         ModResult OnUserPreKick(User* source, Membership* memb, const std::string &reason) CXX11_OVERRIDE
142         {
143                 // Don't do anything if they're not +Y
144                 if (!memb->HasMode(&np))
145                         return MOD_RES_PASSTHRU;
146
147                 // Let them do whatever they want to themselves.
148                 if (source == memb->user)
149                         return MOD_RES_PASSTHRU;
150
151                 source->WriteNumeric(ERR_RESTRICTED, memb->chan->name, "Can't kick "+memb->user->nick+" as they're on official network business.");
152                 return MOD_RES_DENY;
153         }
154
155         void Prioritize() CXX11_OVERRIDE
156         {
157                 ServerInstance->Modules->SetPriority(this, I_OnUserPreJoin, PRIORITY_FIRST);
158         }
159
160         Version GetVersion() CXX11_OVERRIDE
161         {
162                 return Version("Adds the /OJOIN command which allows server operators to join a channel and receive the server operator-only Y (official-join) channel prefix mode.", VF_VENDOR);
163         }
164 };
165
166 MODULE_INIT(ModuleOjoin)