]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_nicklock.cpp
Fix for some modules sending global snotices at each individual server in a server...
[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
23  public:
24         CommandNicklock (InspIRCd* Instance) : Command(Instance,"NICKLOCK", "o", 2)
25         {
26                 this->source = "m_nicklock.so";
27                 syntax = "<oldnick> <newnick>";
28                 TRANSLATE3(TR_NICK, TR_TEXT, TR_END);
29         }
30
31         CmdResult Handle(const std::vector<std::string>& parameters, User *user)
32         {
33                 User* target = ServerInstance->FindNick(parameters[0]);
34
35                 /* Do local sanity checks and bails */
36                 if (IS_LOCAL(user))
37                 {
38                         if (target && ServerInstance->ULine(target->server))
39                         {
40                                 user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Cannot use an NICKLOCK command on a u-lined client",user->nick.c_str());
41                                 return CMD_FAILURE;
42                         }
43
44                         if (!target)
45                         {
46                                 user->WriteServ("NOTICE %s :*** No such nickname: '%s'", user->nick.c_str(), parameters[0].c_str());
47                                 return CMD_FAILURE;
48                         }
49
50                         if (target->GetExt("nick_locked"))
51                         {
52                                 user->WriteNumeric(946, "%s %s :This user's nickname is already locked.",user->nick.c_str(),target->nick.c_str());
53                                 return CMD_FAILURE;
54                         }
55
56                         if (!ServerInstance->IsNick(parameters[1].c_str(), ServerInstance->Config->Limits.NickMax))
57                         {
58                                 user->WriteServ("NOTICE %s :*** Invalid nickname '%s'", user->nick.c_str(), parameters[1].c_str());
59                                 return CMD_FAILURE;
60                         }
61
62                         user->WriteServ("947 %s %s :Nickname now locked.", user->nick.c_str(), parameters[1].c_str());
63                 }
64
65                 /* If we made it this far, extend the user */
66                 if (target)
67                 {
68                         // This has to be done *here*, because this metadata must be stored netwide.
69                         target->Extend("nick_locked", "ON");
70
71                         /* Only send out nick from local server */
72                         if (IS_LOCAL(target))
73                         {
74                                 ServerInstance->SNO->WriteGlobalSno('a', user->nick+" used NICKLOCK to change and hold "+target->nick+" to "+parameters[1]);
75                                 std::string oldnick = user->nick;
76                                 std::string newnick = target->nick;
77                                 if (!target->ForceNickChange(parameters[1].c_str()))
78                                 {
79                                         /* XXX: We failed, this *should* not happen but if it does
80                                          * tell everybody. Note user is still nick locked on their old
81                                          * nick instead.
82                                          */
83                                         ServerInstance->SNO->WriteToSnoMask('a', oldnick+" failed nickchange on NICKLOCK (from "+newnick+" to "+parameters[1]+") Locked to "+newnick+" instead");
84                                         ServerInstance->PI->SendSNONotice("A", oldnick+" failed nickchange on NICKLOCK (from "+newnick+" to "+parameters[1]+") Locked to "+newnick+" instead");
85                                 }
86                         }
87                 }
88
89                 /* Route it */
90                 return CMD_SUCCESS;
91         }
92 };
93
94 /** Handle /NICKUNLOCK
95  */
96 class CommandNickunlock : public Command
97 {
98  public:
99         CommandNickunlock (InspIRCd* Instance) : Command(Instance,"NICKUNLOCK", "o", 1)
100         {
101                 this->source = "m_nicklock.so";
102                 syntax = "<locked-nick>";
103         }
104
105         CmdResult Handle (const std::vector<std::string>& parameters, User *user)
106         {
107                 User* target = ServerInstance->FindNick(parameters[0]);
108
109                 /* Do local sanity checks and bails */
110                 if (IS_LOCAL(user))
111                 {
112                         if (target && ServerInstance->ULine(target->server))
113                         {
114                                 user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Cannot use an NICKUNLOCK command on a u-lined client",user->nick.c_str());
115                                 return CMD_FAILURE;
116                         }
117
118                         if (!target)
119                         {
120                                 user->WriteServ("NOTICE %s :*** No such nickname: '%s'", user->nick.c_str(), parameters[0].c_str());
121                                 return CMD_FAILURE;
122                         }
123
124                         if (!target->GetExt("nick_locked"))
125                         {
126                                 user->WriteNumeric(946, "%s %s :This user's nickname is not locked.",user->nick.c_str(),target->nick.c_str());
127                                 return CMD_FAILURE;
128                         }
129                 }
130
131                 /* If we made it this far, the command is going out on the wire so send local snotice */
132                 ServerInstance->SNO->WriteGlobalSno('a', std::string(user->nick)+" used NICKUNLOCK on "+parameters[0]);
133
134                 if (target)
135                 {
136                         target->Shrink("nick_locked");
137                         if (IS_LOCAL(user))
138                                 user->WriteNumeric(945, "%s %s :Nickname now unlocked.",user->nick.c_str(),target->nick.c_str());
139                 }
140
141                 /* Route it */
142                 return CMD_SUCCESS;
143         }
144 };
145
146
147 class ModuleNickLock : public Module
148 {
149         CommandNicklock*        cmd1;
150         CommandNickunlock*      cmd2;
151         char* n;
152  public:
153         ModuleNickLock(InspIRCd* Me)
154                 : Module(Me)
155         {
156
157                 cmd1 = new CommandNicklock(ServerInstance);
158                 cmd2 = new CommandNickunlock(ServerInstance);
159                 ServerInstance->AddCommand(cmd1);
160                 ServerInstance->AddCommand(cmd2);
161                 Implementation eventlist[] = { I_OnUserPreNick, I_OnUserQuit, I_OnCleanup };
162                 ServerInstance->Modules->Attach(eventlist, this, 3);
163         }
164
165         virtual ~ModuleNickLock()
166         {
167         }
168
169         virtual Version GetVersion()
170         {
171                 return Version("$Id$", VF_COMMON | VF_VENDOR, API_VERSION);
172         }
173
174
175         virtual int OnUserPreNick(User* user, const std::string &newnick)
176         {
177                 if (!IS_LOCAL(user))
178                         return 0;
179
180                 if (isdigit(newnick[0])) /* Allow a switch to a UID */
181                         return 0;
182
183                 if (user->GetExt("NICKForced")) /* Allow forced nick changes */
184                         return 0;
185
186                 if (user->GetExt("nick_locked", n))
187                 {
188                         user->WriteNumeric(447, "%s :You cannot change your nickname (your nick is locked)",user->nick.c_str());
189                         return 1;
190                 }
191                 return 0;
192         }
193
194         virtual void OnUserQuit(User* user, const std::string &reason, const std::string &oper_message)
195         {
196                 user->Shrink("nick_locked");
197         }
198
199         void Prioritize()
200         {
201                 Module *nflood = ServerInstance->Modules->Find("m_nickflood.so");
202                 ServerInstance->Modules->SetPriority(this, I_OnUserPreJoin, PRIORITY_BEFORE, &nflood);
203         }
204
205         virtual void OnCleanup(int target_type, void* item)
206         {
207                 if(target_type == TYPE_USER)
208                 {
209                         User* user = (User*)item;
210                         user->Shrink("nick_locked");
211                 }
212         }
213 };
214
215 MODULE_INIT(ModuleNickLock)