2 * InspIRCd -- Internet Relay Chat Daemon
4 * Copyright (C) 2017, 2020 Sadie Powell <sadie@witchery.services>
5 * Copyright (C) 2013, 2016 Attila Molnar <attilamolnar@hush.com>
6 * Copyright (C) 2012, 2019 Robby <robby@chatbelgie.be>
7 * Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
8 * Copyright (C) 2008, 2010 Craig Edwards <brain@inspircd.org>
9 * Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
10 * Copyright (C) 2006 Robin Burchell <robin+git@viroteck.net>
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.
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
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/>.
27 #include "core_user.h"
29 ModeUserServerNoticeMask::ModeUserServerNoticeMask(Module* Creator)
30 : ModeHandler(Creator, "snomask", 's', PARAM_SETONLY, MODETYPE_USER)
33 syntax = "(+|-)<snomasks>|*";
36 ModeAction ModeUserServerNoticeMask::OnModeChange(User* source, User* dest, Channel*, std::string ¶meter, bool adding)
40 dest->SetMode(this, true);
41 // Process the parameter (remove chars we don't understand, remove redundant chars, etc.)
42 parameter = ProcessNoticeMasks(dest, parameter);
43 return MODEACTION_ALLOW;
47 if (dest->IsModeSet(this))
49 dest->SetMode(this, false);
50 dest->snomasks.reset();
51 return MODEACTION_ALLOW;
55 // Mode not set and trying to unset, deny
56 return MODEACTION_DENY;
59 std::string ModeUserServerNoticeMask::GetUserParameter(const User* user) const
62 if (!user->IsModeSet(this))
66 for (unsigned char n = 0; n < 64; n++)
68 if (user->snomasks[n])
69 ret.push_back(n + 'A');
74 std::string ModeUserServerNoticeMask::ProcessNoticeMasks(User* user, const std::string& input)
77 std::bitset<64> curr = user->snomasks;
79 for (std::string::const_iterator i = input.begin(); i != input.end(); ++i)
90 for (size_t j = 0; j < 64; j++)
92 const char chr = j + 'A';
93 if (user->HasSnomaskPermission(chr) && ServerInstance->SNO->IsSnomaskUsable(chr))
98 // For local users check whether the given snomask is valid and enabled - IsSnomaskUsable() tests both.
99 // For remote users accept what we were told, unless the snomask char is not a letter.
102 if (!ServerInstance->SNO->IsSnomaskUsable(*i))
104 user->WriteNumeric(ERR_UNKNOWNSNOMASK, *i, "is an unknown snomask character");
107 else if (!user->IsOper())
109 user->WriteNumeric(ERR_NOPRIVILEGES, InspIRCd::Format("Permission Denied - Only operators may %sset snomask %c",
110 adding ? "" : "un", *i));
114 else if (!user->HasSnomaskPermission(*i))
116 user->WriteNumeric(ERR_NOPRIVILEGES, InspIRCd::Format("Permission Denied - Oper type %s does not have access to snomask %c",
117 user->oper->name.c_str(), *i));
121 else if (!(((*i >= 'a') && (*i <= 'z')) || ((*i >= 'A') && (*i <= 'Z'))))
124 size_t index = ((*i) - 'A');
125 curr[index] = adding;
130 std::string plus = "+";
131 std::string minus = "-";
133 // Apply changes and construct two strings consisting of the newly added and the removed snomask chars
134 for (size_t i = 0; i < 64; i++)
136 bool isset = curr[i];
137 if (user->snomasks[i] != isset)
139 user->snomasks[i] = isset;
140 std::string& appendhere = (isset ? plus : minus);
141 appendhere.push_back(i+'A');
145 // Create the final string that will be shown to the user and sent to servers
148 if (plus.length() > 1)
151 if (minus.length() > 1)
154 // Unset the snomask usermode itself if every snomask was unset
155 if (user->snomasks.none())
156 user->SetMode(this, false);