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