]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_namedmodes.cpp
Unset umode +x when a different vhost is set on a user
[user/henk/code/inspircd.git] / src / modules / m_namedmodes.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd: (C) 2002-2010 InspIRCd Development Team
6  * See: http://wiki.inspircd.org/Credits
7  *
8  * This program is free but copyrighted software; see
9  *            the file COPYING for details.
10  *
11  * ---------------------------------------------------
12  */
13
14 #include "inspircd.h"
15
16 static void DisplayList(User* user, Channel* channel)
17 {
18         std::stringstream items;
19         for(char letter = 'A'; letter <= 'z'; letter++)
20         {
21                 ModeHandler* mh = ServerInstance->Modes->FindMode(letter, MODETYPE_CHANNEL);
22                 if (!mh || mh->IsListMode())
23                         continue;
24                 if (!channel->IsModeSet(letter))
25                         continue;
26                 items << " +" << mh->name;
27                 if (mh->GetNumParams(true))
28                         items << " " << channel->GetModeParameter(letter);
29         }
30         char pfx[MAXBUF];
31         snprintf(pfx, MAXBUF, ":%s 961 %s %s", ServerInstance->Config->ServerName.c_str(), user->nick.c_str(), channel->name.c_str());
32         user->SendText(std::string(pfx), items);
33         user->WriteNumeric(960, "%s %s :End of mode list", user->nick.c_str(), channel->name.c_str());
34 }
35
36 class CommandProp : public Command
37 {
38  public:
39         CommandProp(Module* parent) : Command(parent, "PROP", 1)
40         {
41                 syntax = "<user|channel> {[+-]<mode> [<value>]}*";
42         }
43
44         CmdResult Handle(const std::vector<std::string> &parameters, User *src)
45         {
46                 if (parameters.size() == 1)
47                 {
48                         Channel* chan = ServerInstance->FindChan(parameters[0]);
49                         if (chan)
50                                 DisplayList(src, chan);
51                         return CMD_SUCCESS;
52                 }
53                 unsigned int i = 1;
54                 std::vector<std::string> modes;
55                 modes.push_back(parameters[0]);
56                 modes.push_back("");
57                 while (i < parameters.size())
58                 {
59                         std::string prop = parameters[i++];
60                         bool plus = prop[0] != '-';
61                         if (prop[0] == '+' || prop[0] == '-')
62                                 prop.erase(prop.begin());
63
64                         for(char letter = 'A'; letter <= 'z'; letter++)
65                         {
66                                 ModeHandler* mh = ServerInstance->Modes->FindMode(letter, MODETYPE_CHANNEL);
67                                 if (mh && mh->name == prop)
68                                 {
69                                         modes[1].append((plus ? "+" : "-") + std::string(1, letter));
70                                         if (mh->GetNumParams(plus))
71                                         {
72                                                 if (i != parameters.size())
73                                                         modes.push_back(parameters[i++]);
74                                         }
75                                 }
76                         }
77                 }
78                 ServerInstance->SendGlobalMode(modes, src);
79                 return CMD_SUCCESS;
80         }
81 };
82
83 class ModuleNamedModes : public Module
84 {
85         CommandProp cmd;
86  public:
87         ModuleNamedModes() : cmd(this)
88         {
89         }
90
91         void init()
92         {
93                 ServerInstance->Modules->AddService(cmd);
94
95                 Implementation eventlist[] = { I_OnPreMode, I_On005Numeric };
96                 ServerInstance->Modules->Attach(eventlist, this, 2);
97         }
98
99         Version GetVersion()
100         {
101                 return Version("Provides the ability to manipulate modes via long names.",VF_VENDOR);
102         }
103
104         void Prioritize()
105         {
106                 ServerInstance->Modules->SetPriority(this, I_OnPreMode, PRIORITY_FIRST);
107         }
108
109         void On005Numeric(std::string& line)
110         {
111                 std::string::size_type pos = line.find(" CHANMODES=");
112                 if (pos != std::string::npos)
113                 {
114                         pos += 11;
115                         while (line[pos] > 'A' && line[pos] < 'Z')
116                                 pos++;
117                         line.insert(pos, 1, 'Z');
118                 }
119         }
120
121         ModResult OnPreMode(User* source, User* dest, Channel* channel, const std::vector<std::string>& parameters)
122         {
123                 if (!channel)
124                         return MOD_RES_PASSTHRU;
125                 if (parameters[1].find('Z') == std::string::npos)
126                         return MOD_RES_PASSTHRU;
127                 if (parameters.size() <= 2)
128                 {
129                         DisplayList(source, channel);
130                         return MOD_RES_DENY;
131                 }
132
133                 std::vector<std::string> newparms;
134                 newparms.push_back(parameters[0]);
135                 newparms.push_back(parameters[1]);
136
137                 std::string modelist = newparms[1];
138                 bool adding = true;
139                 unsigned int param_at = 2;
140                 for(unsigned int i = 0; i < modelist.length(); i++)
141                 {
142                         unsigned char modechar = modelist[i];
143                         if (modechar == '+' || modechar == '-')
144                         {
145                                 adding = (modechar == '+');
146                                 continue;
147                         }
148                         ModeHandler *mh = ServerInstance->Modes->FindMode(modechar, MODETYPE_CHANNEL);
149                         if (modechar == 'Z')
150                         {
151                                 modechar = 0;
152                                 std::string name, value;
153                                 if (param_at < parameters.size())
154                                         name = parameters[param_at++];
155                                 std::string::size_type eq = name.find('=');
156                                 if (eq != std::string::npos)
157                                 {
158                                         value = name.substr(eq + 1);
159                                         name = name.substr(0, eq);
160                                 }
161                                 for(char letter = 'A'; modechar == 0 && letter <= 'z'; letter++)
162                                 {
163                                         mh = ServerInstance->Modes->FindMode(letter, MODETYPE_CHANNEL);
164                                         if (mh && mh->name == name)
165                                         {
166                                                 if (mh->GetNumParams(adding))
167                                                 {
168                                                         if (!value.empty())
169                                                         {
170                                                                 newparms.push_back(value);
171                                                                 modechar = letter;
172                                                                 break;
173                                                         }
174                                                 }
175                                                 else
176                                                 {
177                                                         modechar = letter;
178                                                         break;
179                                                 }
180                                         }
181                                 }
182                                 if (modechar)
183                                         modelist[i] = modechar;
184                                 else
185                                         modelist.erase(i--, 1);
186                         }
187                         else if (mh && mh->GetNumParams(adding) && param_at < parameters.size())
188                         {
189                                 newparms.push_back(parameters[param_at++]);
190                         }
191                 }
192                 newparms[1] = modelist;
193                 ServerInstance->Modes->Process(newparms, source, false);
194                 return MOD_RES_DENY;
195         }
196 };
197
198 MODULE_INIT(ModuleNamedModes)