]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_nicklock.cpp
fe669fdcb41a5f068f5e277d851a852b73e88e97
[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 (target)
132                 {
133                         target->Shrink("nick_locked");
134                         if (IS_LOCAL(target))
135                                 ServerInstance->SNO->WriteGlobalSno('a', std::string(user->nick)+" used NICKUNLOCK on "+parameters[0]);
136                         if (IS_LOCAL(user))
137                                 user->WriteNumeric(945, "%s %s :Nickname now unlocked.",user->nick.c_str(),target->nick.c_str());
138                 }
139
140                 /* Route it */
141                 return CMD_SUCCESS;
142         }
143 };
144
145
146 class ModuleNickLock : public Module
147 {
148         CommandNicklock*        cmd1;
149         CommandNickunlock*      cmd2;
150         char* n;
151  public:
152         ModuleNickLock(InspIRCd* Me)
153                 : Module(Me)
154         {
155
156                 cmd1 = new CommandNicklock(ServerInstance);
157                 cmd2 = new CommandNickunlock(ServerInstance);
158                 ServerInstance->AddCommand(cmd1);
159                 ServerInstance->AddCommand(cmd2);
160                 Implementation eventlist[] = { I_OnUserPreNick, I_OnUserQuit, I_OnCleanup };
161                 ServerInstance->Modules->Attach(eventlist, this, 3);
162         }
163
164         virtual ~ModuleNickLock()
165         {
166         }
167
168         virtual Version GetVersion()
169         {
170                 return Version("$Id$", VF_COMMON | VF_VENDOR, API_VERSION);
171         }
172
173
174         virtual int OnUserPreNick(User* user, const std::string &newnick)
175         {
176                 if (!IS_LOCAL(user))
177                         return 0;
178
179                 if (isdigit(newnick[0])) /* Allow a switch to a UID */
180                         return 0;
181
182                 if (user->GetExt("NICKForced")) /* Allow forced nick changes */
183                         return 0;
184
185                 if (user->GetExt("nick_locked", n))
186                 {
187                         user->WriteNumeric(447, "%s :You cannot change your nickname (your nick is locked)",user->nick.c_str());
188                         return 1;
189                 }
190                 return 0;
191         }
192
193         virtual void OnUserQuit(User* user, const std::string &reason, const std::string &oper_message)
194         {
195                 user->Shrink("nick_locked");
196         }
197
198         void Prioritize()
199         {
200                 Module *nflood = ServerInstance->Modules->Find("m_nickflood.so");
201                 ServerInstance->Modules->SetPriority(this, I_OnUserPreJoin, PRIORITY_BEFORE, &nflood);
202         }
203
204         virtual void OnCleanup(int target_type, void* item)
205         {
206                 if(target_type == TYPE_USER)
207                 {
208                         User* user = (User*)item;
209                         user->Shrink("nick_locked");
210                 }
211         }
212 };
213
214 MODULE_INIT(ModuleNickLock)