]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/coremods/core_user/umode_s.cpp
4c3725ee5c6fcf476add26c32a0c04f44ef31fc4
[user/henk/code/inspircd.git] / src / coremods / core_user / 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 "core_user.h"
24
25 ModeUserServerNoticeMask::ModeUserServerNoticeMask(Module* Creator)
26         : ModeHandler(Creator, "snomask", 's', PARAM_SETONLY, MODETYPE_USER)
27 {
28         oper = true;
29         syntax = "(+|-)<snomasks>";
30 }
31
32 ModeAction ModeUserServerNoticeMask::OnModeChange(User* source, User* dest, Channel*, std::string &parameter, bool adding)
33 {
34         if (adding)
35         {
36                 dest->SetMode(this, true);
37                 // Process the parameter (remove chars we don't understand, remove redundant chars, etc.)
38                 parameter = ProcessNoticeMasks(dest, parameter);
39                 return MODEACTION_ALLOW;
40         }
41         else
42         {
43                 if (dest->IsModeSet(this))
44                 {
45                         dest->SetMode(this, false);
46                         dest->snomasks.reset();
47                         return MODEACTION_ALLOW;
48                 }
49         }
50
51         // Mode not set and trying to unset, deny
52         return MODEACTION_DENY;
53 }
54
55 std::string ModeUserServerNoticeMask::GetUserParameter(const User* user) const
56 {
57         std::string ret;
58         if (!user->IsModeSet(this))
59                 return ret;
60
61         ret.push_back('+');
62         for (unsigned char n = 0; n < 64; n++)
63         {
64                 if (user->snomasks[n])
65                         ret.push_back(n + 'A');
66         }
67         return ret;
68 }
69
70 void ModeUserServerNoticeMask::OnParameterMissing(User* user, User* dest, Channel* channel)
71 {
72         user->WriteNotice("*** The user mode +s requires a parameter (server notice mask). Please provide a parameter, e.g. '+s +*'.");
73 }
74
75 std::string ModeUserServerNoticeMask::ProcessNoticeMasks(User* user, const std::string& input)
76 {
77         bool adding = true;
78         std::bitset<64> curr = user->snomasks;
79
80         for (std::string::const_iterator i = input.begin(); i != input.end(); ++i)
81         {
82                 switch (*i)
83                 {
84                         case '+':
85                                 adding = true;
86                         break;
87                         case '-':
88                                 adding = false;
89                         break;
90                         case '*':
91                                 for (size_t j = 0; j < 64; j++)
92                                 {
93                                         if (ServerInstance->SNO->IsSnomaskUsable(j+'A'))
94                                                 curr[j] = adding;
95                                 }
96                         break;
97                         default:
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.
100                                 if (IS_LOCAL(user))
101                                 {
102                                         if (!ServerInstance->SNO->IsSnomaskUsable(*i))
103                                         {
104                                                 user->WriteNumeric(ERR_UNKNOWNSNOMASK, *i, "is an unknown snomask character");
105                                                 continue;
106                                         }
107                                 }
108                                 else if (!(((*i >= 'a') && (*i <= 'z')) || ((*i >= 'A') && (*i <= 'Z'))))
109                                         continue;
110
111                                 size_t index = ((*i) - 'A');
112                                 curr[index] = adding;
113                         break;
114                 }
115         }
116
117         std::string plus = "+";
118         std::string minus = "-";
119
120         // Apply changes and construct two strings consisting of the newly added and the removed snomask chars
121         for (size_t i = 0; i < 64; i++)
122         {
123                 bool isset = curr[i];
124                 if (user->snomasks[i] != isset)
125                 {
126                         user->snomasks[i] = isset;
127                         std::string& appendhere = (isset ? plus : minus);
128                         appendhere.push_back(i+'A');
129                 }
130         }
131
132         // Create the final string that will be shown to the user and sent to servers
133         // Form: "+ABc-de"
134         std::string output;
135         if (plus.length() > 1)
136                 output = plus;
137
138         if (minus.length() > 1)
139                 output += minus;
140
141         // Unset the snomask usermode itself if every snomask was unset
142         if (user->snomasks.none())
143                 user->SetMode(this, false);
144
145         return output;
146 }