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