]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_namedmodes.cpp
allow channels starting with ## in m_banredirect.cpp, fixes bug #921 reported by...
[user/henk/code/inspircd.git] / src / modules / m_namedmodes.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd: (C) 2002-2009 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 class ModuleNamedModes : public Module
17 {
18  public:
19         ModuleNamedModes()
20         {
21                 Implementation eventlist[] = { I_OnPreMode, I_On005Numeric };
22                 ServerInstance->Modules->Attach(eventlist, this, 2);
23         }
24
25         Version GetVersion()
26         {
27                 return Version("Provides the ability to manipulate modes via long names.",VF_VENDOR);
28         }
29
30         void Prioritize()
31         {
32                 ServerInstance->Modules->SetPriority(this, I_OnPreMode, PRIORITY_FIRST);
33         }
34
35         void On005Numeric(std::string& line)
36         {
37                 std::string::size_type pos = line.find(" CHANMODES=");
38                 if (pos != std::string::npos)
39                 {
40                         pos += 11;
41                         while (line[pos] > 'A' && line[pos] < 'Z')
42                                 pos++;
43                         line.insert(pos, 1, 'Z');
44                 }
45         }
46
47         void DisplayList(User* user, Channel* channel)
48         {
49                 std::stringstream items;
50                 for(char letter = 'A'; letter <= 'z'; letter++)
51                 {
52                         ModeHandler* mh = ServerInstance->Modes->FindMode(letter, MODETYPE_CHANNEL);
53                         if (!mh || mh->IsListMode())
54                                 continue;
55                         if (!channel->IsModeSet(letter))
56                                 continue;
57                         std::string item = mh->name;
58                         if (mh->GetNumParams(true))
59                                 item += "=" + channel->GetModeParameter(letter);
60                         items << item << " ";
61                 }
62                 char pfx[MAXBUF];
63                 snprintf(pfx, MAXBUF, ":%s 961 %s %s", ServerInstance->Config->ServerName.c_str(), user->nick.c_str(), channel->name.c_str());
64                 user->SendText(std::string(pfx), items);
65                 user->WriteNumeric(960, "%s %s :End of mode list", user->nick.c_str(), channel->name.c_str());
66         }
67
68         ModResult OnPreMode(User* source, User* dest, Channel* channel, const std::vector<std::string>& parameters)
69         {
70                 if (!channel)
71                         return MOD_RES_PASSTHRU;
72                 if (parameters[1].find('Z') == std::string::npos)
73                         return MOD_RES_PASSTHRU;
74                 if (parameters.size() <= 2)
75                 {
76                         DisplayList(source, channel);
77                         return MOD_RES_DENY;
78                 }
79
80                 std::vector<std::string> newparms;
81                 newparms.push_back(parameters[0]);
82                 newparms.push_back(parameters[1]);
83
84                 std::string modelist = newparms[1];
85                 bool adding = true;
86                 unsigned int param_at = 2;
87                 for(unsigned int i = 0; i < modelist.length(); i++)
88                 {
89                         unsigned char modechar = modelist[i];
90                         if (modechar == '+' || modechar == '-')
91                         {
92                                 adding = (modechar == '+');
93                                 continue;
94                         }
95                         ModeHandler *mh = ServerInstance->Modes->FindMode(modechar, MODETYPE_CHANNEL);
96                         if (modechar == 'Z')
97                         {
98                                 modechar = 0;
99                                 std::string name, value;
100                                 if (param_at < parameters.size())
101                                         name = parameters[param_at++];
102                                 std::string::size_type eq = name.find('=');
103                                 if (eq != std::string::npos)
104                                 {
105                                         value = name.substr(eq + 1);
106                                         name = name.substr(0, eq);
107                                 }
108                                 for(char letter = 'A'; modechar == 0 && letter <= 'z'; letter++)
109                                 {
110                                         mh = ServerInstance->Modes->FindMode(letter, MODETYPE_CHANNEL);
111                                         if (mh && mh->name == name)
112                                         {
113                                                 if (mh->GetNumParams(adding))
114                                                 {
115                                                         if (!value.empty())
116                                                         {
117                                                                 newparms.push_back(value);
118                                                                 modechar = letter;
119                                                                 break;
120                                                         }
121                                                 }
122                                                 else
123                                                 {
124                                                         modechar = letter;
125                                                         break;
126                                                 }
127                                         }
128                                 }
129                                 if (modechar)
130                                         modelist[i] = modechar;
131                                 else
132                                         modelist.erase(i, 1);
133                         }
134                         else if (mh && mh->GetNumParams(adding) && param_at < parameters.size())
135                         {
136                                 newparms.push_back(parameters[param_at++]);
137                         }
138                 }
139                 newparms[1] = modelist;
140                 ServerInstance->Modes->Process(newparms, source, false);
141                 return MOD_RES_DENY;
142         }
143 };
144
145 MODULE_INIT(ModuleNamedModes)