]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_alias.cpp
OOPS! We try again, since I'm smoking craq. LF is 0x0a NOT CR.
[user/henk/code/inspircd.git] / src / modules / m_alias.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd: (C) 2002-2007 InspIRCd Development Team
6  * See: http://www.inspircd.org/wiki/index.php/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 #include "users.h"
16 #include "channels.h"
17 #include "modules.h"
18 #include "wildcard.h"
19
20 /* $ModDesc: Provides aliases of commands. */
21
22 /** An alias definition
23  */
24 class Alias : public classbase
25 {
26  public:
27         /** The text of the alias command */
28         irc::string text;
29         /** Text to replace with */
30         std::string replace_with;
31         /** Nickname required to perform alias */
32         std::string requires;
33         /** Alias requires ulined server */
34         bool uline;
35         /** Requires oper? */
36         bool operonly;
37         /* is case sensitive params */
38         bool case_sensitive;
39         /** Format that must be matched for use */
40         std::string format;
41 };
42
43 class ModuleAlias : public Module
44 {
45  private:
46         /** We cant use a map, there may be multiple aliases with the same name */
47         std::vector<Alias> Aliases;
48         std::map<std::string, int> AliasMap;
49         std::vector<std::string> pars;
50
51         virtual void ReadAliases()
52         {
53                 ConfigReader MyConf(ServerInstance);
54
55                 Aliases.clear();
56                 AliasMap.clear();
57                 for (int i = 0; i < MyConf.Enumerate("alias"); i++)
58                 {
59                         Alias a;
60                         std::string txt;
61                         txt = MyConf.ReadValue("alias", "text", i);
62                         a.text = txt.c_str();
63                         a.replace_with = MyConf.ReadValue("alias", "replace", i, true);
64                         a.requires = MyConf.ReadValue("alias", "requires", i);
65                         a.uline = MyConf.ReadFlag("alias", "uline", i);
66                         a.operonly = MyConf.ReadFlag("alias", "operonly", i);
67                         a.format = MyConf.ReadValue("alias", "format", i);
68                         a.case_sensitive = MyConf.ReadFlag("alias", "matchcase", i);
69                         Aliases.push_back(a);
70                         AliasMap[txt] = 1;
71                 }
72         }
73
74  public:
75         
76         ModuleAlias(InspIRCd* Me)
77                 : Module(Me)
78         {
79                 ReadAliases();
80                 pars.resize(127);
81         }
82
83         void Implements(char* List)
84         {
85                 List[I_OnPreCommand] = List[I_OnRehash] = 1;
86         }
87
88         virtual ~ModuleAlias()
89         {
90         }
91
92         virtual Version GetVersion()
93         {
94                 return Version(1,1,0,1,VF_VENDOR,API_VERSION);
95         }
96
97         std::string GetVar(std::string varname, const std::string &original_line)
98         {
99                 irc::spacesepstream ss(original_line);
100                 varname.erase(varname.begin());
101                 int index = *(varname.begin()) - 48;
102                 varname.erase(varname.begin());
103                 bool everything_after = (varname == "-");
104                 std::string word;
105
106                 for (int j = 0; j < index; j++)
107                         word = ss.GetToken();
108
109                 if (everything_after)
110                 {
111                         std::string more = "*";
112                         while ((more = ss.GetToken()) != "")
113                         {
114                                 word.append(" ");
115                                 word.append(more);
116                         }
117                 }
118
119                 return word;
120         }
121
122         void SearchAndReplace(std::string& newline, const std::string &find, const std::string &replace)
123         {
124                 std::string::size_type x = newline.find(find);
125                 while (x != std::string::npos)
126                 {
127                         newline.erase(x, find.length());
128                         newline.insert(x, replace);
129                         x = newline.find(find);
130                 }
131         }
132
133         virtual int OnPreCommand(const std::string &command, const char** parameters, int pcnt, userrec *user, bool validated, const std::string &original_line)
134         {
135                 userrec *u = NULL;
136
137                 /* If theyre not registered yet, we dont want
138                  * to know.
139                  */
140                 if (user->registered != REG_ALL)
141                         return 0;
142
143                 /* We dont have any commands looking like this, dont bother with the loop */
144                 if (AliasMap.find(command) == AliasMap.end())
145                         return 0;
146
147                 irc::string c = command.c_str();
148                 /* The parameters for the command in their original form, with the command stripped off */
149                 std::string compare = original_line.substr(command.length());
150                 while (*(compare.c_str()) == ' ')
151                         compare.erase(compare.begin());
152
153                 std::string safe(original_line);
154
155                 /* Escape out any $ symbols in the user provided text */
156
157                 SearchAndReplace(safe, "$", "\r");
158
159                 for (unsigned int i = 0; i < Aliases.size(); i++)
160                 {
161                         if (Aliases[i].text == c)
162                         {
163                                 /* Does it match the pattern? */
164                                 if (!Aliases[i].format.empty())
165                                 {
166                                         if (!match(Aliases[i].case_sensitive, compare.c_str(), Aliases[i].format.c_str()))
167                                                 continue;
168                                 }
169
170                                 if ((Aliases[i].operonly) && (!IS_OPER(user)))
171                                         return 0;
172
173                                 if (!Aliases[i].requires.empty())
174                                 {
175                                         u = ServerInstance->FindNick(Aliases[i].requires);
176                                         if (!u)
177                                         {
178                                                 user->WriteServ("401 "+std::string(user->nick)+" "+Aliases[i].requires+" :is currently unavailable. Please try again later.");
179                                                 return 1;
180                                         }
181                                 }
182                                 if ((u != NULL) && (!Aliases[i].requires.empty()) && (Aliases[i].uline))
183                                 {
184                                         if (!ServerInstance->ULine(u->server))
185                                         {
186                                                 ServerInstance->WriteOpers("*** NOTICE -- Service "+Aliases[i].requires+" required by alias "+std::string(Aliases[i].text.c_str())+" is not on a u-lined server, possibly underhanded antics detected!"); 
187                                                 user->WriteServ("401 "+std::string(user->nick)+" "+Aliases[i].requires+" :is an imposter! Please inform an IRC operator as soon as possible.");
188                                                 return 1;
189                                         }
190                                 }
191
192                                 /* Now, search and replace in a copy of the original_line, replacing $1 through $9 and $1- etc */
193
194                                 std::string::size_type crlf = Aliases[i].replace_with.find('\n');
195
196                                 if (crlf == std::string::npos)
197                                 {
198                                         DoCommand(Aliases[i].replace_with, user, safe);
199                                         return 1;
200                                 }
201                                 else
202                                 {
203                                         irc::sepstream commands(Aliases[i].replace_with, '\n');
204                                         std::string command = "*";
205                                         while ((command = commands.GetToken()) != "")
206                                         {
207                                                 DoCommand(command, user, safe);
208                                         }
209                                         return 1;
210                                 }
211                         }
212                 }
213                 return 0;
214         }
215
216         void DoCommand(std::string newline, userrec* user, const std::string &original_line)
217         {
218                 for (int v = 1; v < 10; v++)
219                 {
220                         std::string var = "$";
221                         var.append(ConvToStr(v));
222                         var.append("-");
223                         std::string::size_type x = newline.find(var);
224
225                         while (x != std::string::npos)
226                         {
227                                 newline.erase(x, var.length());
228                                 newline.insert(x, GetVar(var, original_line));
229                                 x = newline.find(var);
230                         }
231
232                         var = "$";
233                         var.append(ConvToStr(v));
234                         x = newline.find(var);
235
236                         while (x != std::string::npos)
237                         {
238                                 newline.erase(x, var.length());
239                                 newline.insert(x, GetVar(var, original_line));
240                                 x = newline.find(var);
241                         }
242                 }
243
244                 /* Special variables */
245                 SearchAndReplace(newline, "$nick", user->nick);
246                 SearchAndReplace(newline, "$ident", user->ident);
247                 SearchAndReplace(newline, "$host", user->host);
248                 SearchAndReplace(newline, "$vhost", user->dhost);
249
250                 /* Unescape any variable names in the user text before sending */
251                 SearchAndReplace(newline, "\r", "$");
252
253                 irc::tokenstream ss(newline);
254                 const char* parv[127];
255                 int x = 0;
256
257                 while (ss.GetToken(pars[x]))
258                 {
259                         parv[x] = pars[x].c_str();
260                         x++;
261                 }
262
263                 ServerInstance->Parser->CallHandler(parv[0], &parv[1], x-1, user);
264         }
265  
266         virtual void OnRehash(userrec* user, const std::string &parameter)
267         {
268                 ReadAliases();
269         }
270 };
271
272 MODULE_INIT(ModuleAlias)