]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modes/umode_s.cpp
Hide all symbols that aren't exported explicitly
[user/henk/code/inspircd.git] / src / modes / umode_s.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2008 Robin Burchell <robin+git@viroteck.net>
5  *   Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
6  *   Copyright (C) 2006 Craig Edwards <craigedwards@brainbox.cc>
7  *
8  * This file is part of InspIRCd.  InspIRCd is free software: you can
9  * redistribute it and/or modify it under the terms of the GNU General Public
10  * License as published by the Free Software Foundation, version 2.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
15  * details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21
22 #include "inspircd.h"
23 #include "mode.h"
24 #include "channels.h"
25 #include "users.h"
26 #include "builtinmodes.h"
27
28 ModeUserServerNoticeMask::ModeUserServerNoticeMask() : ModeHandler(NULL, "snomask", 's', PARAM_SETONLY, MODETYPE_USER)
29 {
30         oper = true;
31 }
32
33 ModeAction ModeUserServerNoticeMask::OnModeChange(User* source, User* dest, Channel*, std::string &parameter, bool adding)
34 {
35         if (adding)
36         {
37                 dest->SetMode(this, true);
38                 // Process the parameter (remove chars we don't understand, remove redundant chars, etc.)
39                 parameter = ProcessNoticeMasks(dest, parameter);
40                 return MODEACTION_ALLOW;
41         }
42         else
43         {
44                 if (dest->IsModeSet(this))
45                 {
46                         dest->SetMode(this, false);
47                         dest->snomasks.reset();
48                         return MODEACTION_ALLOW;
49                 }
50         }
51
52         // Mode not set and trying to unset, deny
53         return MODEACTION_DENY;
54 }
55
56 std::string ModeUserServerNoticeMask::GetUserParameter(User* user)
57 {
58         std::string ret;
59         if (!user->IsModeSet(this))
60                 return ret;
61
62         ret.push_back('+');
63         for (unsigned char n = 0; n < 64; n++)
64         {
65                 if (user->snomasks[n])
66                         ret.push_back(n + 'A');
67         }
68         return ret;
69 }
70
71 void ModeUserServerNoticeMask::OnParameterMissing(User* user, User* dest, Channel* channel)
72 {
73         user->WriteNotice("*** The user mode +s requires a parameter (server notice mask). Please provide a parameter, e.g. '+s +*'.");
74 }
75
76 std::string ModeUserServerNoticeMask::ProcessNoticeMasks(User* user, const std::string& input)
77 {
78         bool adding = true;
79         std::bitset<64> curr = user->snomasks;
80
81         for (std::string::const_iterator i = input.begin(); i != input.end(); ++i)
82         {
83                 switch (*i)
84                 {
85                         case '+':
86                                 adding = true;
87                         break;
88                         case '-':
89                                 adding = false;
90                         break;
91                         case '*':
92                                 for (size_t j = 0; j < 64; j++)
93                                 {
94                                         if (ServerInstance->SNO->IsSnomaskUsable(j+'A'))
95                                                 curr[j] = adding;
96                                 }
97                         break;
98                         default:
99                                 // For local users check whether the given snomask is valid and enabled - IsSnomaskUsable() tests both.
100                                 // For remote users accept what we were told, unless the snomask char is not a letter.
101                                 if (IS_LOCAL(user))
102                                 {
103                                         if (!ServerInstance->SNO->IsSnomaskUsable(*i))
104                                         {
105                                                 user->WriteNumeric(ERR_UNKNOWNSNOMASK, "%s %c :is unknown snomask char to me", user->nick.c_str(), *i);
106                                                 continue;
107                                         }
108                                 }
109                                 else if (!(((*i >= 'a') && (*i <= 'z')) || ((*i >= 'A') && (*i <= 'Z'))))
110                                         continue;
111
112                                 size_t index = ((*i) - 'A');
113                                 curr[index] = adding;
114                         break;
115                 }
116         }
117
118         std::string plus = "+";
119         std::string minus = "-";
120
121         // Apply changes and construct two strings consisting of the newly added and the removed snomask chars
122         for (size_t i = 0; i < 64; i++)
123         {
124                 bool isset = curr[i];
125                 if (user->snomasks[i] != isset)
126                 {
127                         user->snomasks[i] = isset;
128                         std::string& appendhere = (isset ? plus : minus);
129                         appendhere.push_back(i+'A');
130                 }
131         }
132
133         // Create the final string that will be shown to the user and sent to servers
134         // Form: "+ABc-de"
135         std::string output;
136         if (plus.length() > 1)
137                 output = plus;
138
139         if (minus.length() > 1)
140                 output += minus;
141
142         // Unset the snomask usermode itself if every snomask was unset
143         if (user->snomasks.none())
144                 user->SetMode(this, false);
145
146         return output;
147 }