]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_nicklock.cpp
Fix infinite loop on alias expansion, found by Adam
[user/henk/code/inspircd.git] / src / modules / m_nicklock.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 /* $ModDesc: Provides the NICKLOCK command, allows an oper to chage a users nick and lock them to it until they quit */
17
18 /** Handle /NICKLOCK
19  */
20 class CommandNicklock : public Command
21 {
22  public:
23         LocalIntExt& locked;
24         CommandNicklock (Module* Creator, LocalIntExt& ext) : Command(Creator,"NICKLOCK", 2),
25                 locked(ext)
26         {
27                 flags_needed = 'o';
28                 syntax = "<oldnick> <newnick>";
29                 TRANSLATE3(TR_NICK, TR_TEXT, TR_END);
30         }
31
32         CmdResult Handle(const std::vector<std::string>& parameters, User *user)
33         {
34                 User* target = ServerInstance->FindNick(parameters[0]);
35
36                 /* Do local sanity checks and bails */
37                 if (IS_LOCAL(user))
38                 {
39                         if (target && ServerInstance->ULine(target->server))
40                         {
41                                 user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Cannot use an NICKLOCK command on a u-lined client",user->nick.c_str());
42                                 return CMD_FAILURE;
43                         }
44
45                         if (!target)
46                         {
47                                 user->WriteServ("NOTICE %s :*** No such nickname: '%s'", user->nick.c_str(), parameters[0].c_str());
48                                 return CMD_FAILURE;
49                         }
50
51                         if (!ServerInstance->IsNick(parameters[1].c_str(), ServerInstance->Config->Limits.NickMax))
52                         {
53                                 user->WriteServ("NOTICE %s :*** Invalid nickname '%s'", user->nick.c_str(), parameters[1].c_str());
54                                 return CMD_FAILURE;
55                         }
56
57                         user->WriteServ("947 %s %s :Nickname now locked.", user->nick.c_str(), parameters[1].c_str());
58                 }
59
60                 /* If we made it this far, extend the user */
61                 if (target && IS_LOCAL(target))
62                 {
63                         locked.set(target, 1);
64
65                         std::string oldnick = target->nick;
66                         if (target->ForceNickChange(parameters[1].c_str()))
67                                 ServerInstance->SNO->WriteGlobalSno('a', user->nick+" used NICKLOCK to change and hold "+oldnick+" to "+parameters[1]);
68                         else
69                         {
70                                 std::string newnick = target->nick;
71                                 ServerInstance->SNO->WriteGlobalSno('a', user->nick+" used NICKLOCK, but "+oldnick+" failed nick change to "+parameters[1]+" and was locked to "+newnick+" instead");
72                         }
73                 }
74
75                 return CMD_SUCCESS;
76         }
77
78         RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters)
79         {
80                 User* dest = ServerInstance->FindNick(parameters[0]);
81                 if (dest)
82                         return ROUTE_OPT_UCAST(dest->server);
83                 return ROUTE_LOCALONLY;
84         }
85 };
86
87 /** Handle /NICKUNLOCK
88  */
89 class CommandNickunlock : public Command
90 {
91  public:
92         LocalIntExt& locked;
93         CommandNickunlock (Module* Creator, LocalIntExt& ext) : Command(Creator,"NICKUNLOCK", 1),
94                 locked(ext)
95         {
96                 flags_needed = 'o';
97                 syntax = "<locked-nick>";
98                 TRANSLATE2(TR_NICK, TR_END);
99         }
100
101         CmdResult Handle (const std::vector<std::string>& parameters, User *user)
102         {
103                 User* target = ServerInstance->FindNick(parameters[0]);
104
105                 /* Do local sanity checks and bails */
106                 if (IS_LOCAL(user))
107                 {
108                         if (target && ServerInstance->ULine(target->server))
109                         {
110                                 user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Cannot use an NICKUNLOCK command on a u-lined client",user->nick.c_str());
111                                 return CMD_FAILURE;
112                         }
113
114                         if (!target)
115                         {
116                                 user->WriteServ("NOTICE %s :*** No such nickname: '%s'", user->nick.c_str(), parameters[0].c_str());
117                                 return CMD_FAILURE;
118                         }
119                 }
120
121                 if (target && IS_LOCAL(target))
122                 {
123                         if (locked.set(target, 0))
124                         {
125                                 ServerInstance->SNO->WriteGlobalSno('a', std::string(user->nick)+" used NICKUNLOCK on "+parameters[0]);
126                                 user->WriteNumeric(945, "%s %s :Nickname now unlocked.",user->nick.c_str(),target->nick.c_str());
127                         }
128                         else
129                         {
130                                 user->WriteNumeric(946, "%s %s :This user's nickname is not locked.",user->nick.c_str(),target->nick.c_str());
131                                 return CMD_FAILURE;
132                         }
133                 }
134
135                 return CMD_SUCCESS;
136         }
137
138         RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters)
139         {
140                 User* dest = ServerInstance->FindNick(parameters[0]);
141                 if (dest)
142                         return ROUTE_OPT_UCAST(dest->server);
143                 return ROUTE_LOCALONLY;
144         }
145 };
146
147
148 class ModuleNickLock : public Module
149 {
150         LocalIntExt locked;
151         CommandNicklock cmd1;
152         CommandNickunlock cmd2;
153  public:
154         ModuleNickLock()
155                 : locked("nick_locked", this), cmd1(this, locked), cmd2(this, locked)
156         {
157                 ServerInstance->AddCommand(&cmd1);
158                 ServerInstance->AddCommand(&cmd2);
159                 ServerInstance->Extensions.Register(&locked);
160                 ServerInstance->Modules->Attach(I_OnUserPreNick, this);
161         }
162
163         ~ModuleNickLock()
164         {
165         }
166
167         Version GetVersion()
168         {
169                 return Version("Provides the NICKLOCK command, allows an oper to chage a users nick and lock them to it until they quit", VF_COMMON | VF_VENDOR);
170         }
171
172
173         ModResult OnUserPreNick(User* user, const std::string &newnick)
174         {
175                 if (!IS_LOCAL(user))
176                         return MOD_RES_PASSTHRU;
177
178                 if (isdigit(newnick[0])) /* Allow a switch to a UID */
179                         return MOD_RES_PASSTHRU;
180
181                 if (ServerInstance->NICKForced.get(user)) /* Allow forced nick changes */
182                         return MOD_RES_PASSTHRU;
183
184                 if (locked.get(user))
185                 {
186                         user->WriteNumeric(447, "%s :You cannot change your nickname (your nick is locked)",user->nick.c_str());
187                         return MOD_RES_DENY;
188                 }
189                 return MOD_RES_PASSTHRU;
190         }
191
192         void Prioritize()
193         {
194                 Module *nflood = ServerInstance->Modules->Find("m_nickflood.so");
195                 ServerInstance->Modules->SetPriority(this, I_OnUserPreJoin, PRIORITY_BEFORE, &nflood);
196         }
197 };
198
199 MODULE_INIT(ModuleNickLock)