]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/cmd_nick.cpp
Add <options:cyclehosts> which allows a user to appear to have quit when their host...
[user/henk/code/inspircd.git] / src / cmd_nick.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
6  *                       E-mail:
7  *                <brain@chatspike.net>
8  *                <Craig@chatspike.net>
9  *
10  * Written by Craig Edwards, Craig McLure, and others.
11  * This program is free but copyrighted software; see
12  *            the file COPYING for details.
13  *
14  * ---------------------------------------------------
15  */
16
17 #include <string>
18 #include <vector>
19 #include "inspircd_config.h"
20 #include "configreader.h"
21 #include "hash_map.h"
22 #include "users.h"
23 #include "modules.h"
24 #include "commands.h"
25 #include "xline.h"
26 #include "dns.h"
27
28 #include "inspircd.h"
29 #include "hashcomp.h"
30 #include "commands/cmd_nick.h"
31
32 void cmd_nick::Handle (const char** parameters, int pcnt, userrec *user)
33 {
34         char oldnick[NICKMAX];
35
36         if (pcnt < 1) 
37         {
38                 ServerInstance->Log(DEBUG,"not enough params for handle_nick");
39                 return;
40         }
41         if (!parameters[0])
42         {
43                 ServerInstance->Log(DEBUG,"invalid parameter passed to handle_nick");
44                 return;
45         }
46         if (!parameters[0][0])
47         {
48                 ServerInstance->Log(DEBUG,"zero length new nick passed to handle_nick");
49                 return;
50         }
51         if (!user)
52         {
53                 ServerInstance->Log(DEBUG,"invalid user passed to handle_nick");
54                 return;
55         }
56         if (!user->nick)
57         {
58                 ServerInstance->Log(DEBUG,"invalid old nick passed to handle_nick");
59                 return;
60         }
61         if (irc::string(user->nick) == irc::string(parameters[0]))
62         {
63                 /* If its exactly the same, even case, dont do anything. */
64                 if (!strcmp(user->nick,parameters[0]))
65                         return;
66                 /* Its a change of case. People insisted that they should be
67                  * able to do silly things like this even though the RFC says
68                  * the nick AAA is the same as the nick aaa.
69                  */
70                 ServerInstance->Log(DEBUG,"old nick is new nick, not updating hash (case change only)");
71                 strlcpy(oldnick, user->nick, NICKMAX - 1);
72                 int MOD_RESULT = 0;
73                 FOREACH_RESULT(I_OnUserPreNick,OnUserPreNick(user,parameters[0]));
74                 if (MOD_RESULT)
75                         return;
76                 if (user->registered == REG_ALL)
77                         user->WriteCommon("NICK %s",parameters[0]);
78                 strlcpy(user->nick, parameters[0], NICKMAX - 1);
79                 FOREACH_MOD(I_OnUserPostNick,OnUserPostNick(user,oldnick));
80                 return;
81         }
82         else
83         {
84                 if ((*parameters[0] == ':') && (*(parameters[0]+1) != 0))
85                 {
86                         parameters[0]++;
87                 }
88                 char* mq = ServerInstance->XLines->matches_qline(parameters[0]);
89                 if (mq)
90                 {
91                         ServerInstance->WriteOpers("*** Q-Lined nickname %s from %s!%s@%s: %s",parameters[0],user->nick,user->ident,user->host,mq);
92                         user->WriteServ("432 %s %s :Invalid nickname: %s",user->nick,parameters[0],mq);
93                         return;
94                 }
95                 if ((ServerInstance->FindNick(parameters[0])) && (ServerInstance->FindNick(parameters[0]) != user))
96                 {
97                         user->WriteServ("433 %s %s :Nickname is already in use.",user->nick,parameters[0]);
98                         return;
99                 }
100         }
101         if ((!ServerInstance->IsNick(parameters[0])) && (IS_LOCAL(user)))
102         {
103                 user->WriteServ("432 %s %s :Erroneous Nickname",user->nick,parameters[0]);
104                 return;
105         }
106
107         if (user->registered == REG_ALL)
108         {
109                 int MOD_RESULT = 0;
110                 FOREACH_RESULT(I_OnUserPreNick,OnUserPreNick(user,parameters[0]));
111                 if (MOD_RESULT) {
112                         // if a module returns true, the nick change is silently forbidden.
113                         return;
114                 }
115
116                 user->WriteCommon("NICK %s",parameters[0]);
117                 
118         }
119
120         strlcpy(oldnick, user->nick, NICKMAX - 1);
121
122         /* change the nick of the user in the users_hash */
123         user = user->UpdateNickHash(parameters[0]);
124         /* actually change the nick within the record */
125         if (!user) return;
126         if (!user->nick) return;
127
128         strlcpy(user->nick, parameters[0], NICKMAX - 1);
129
130         ServerInstance->Log(DEBUG,"new nick set: %s",user->nick);
131         
132         if (user->registered < REG_NICKUSER)
133         {
134                 user->registered = (user->registered | REG_NICK);
135                 // dont attempt to look up the dns until they pick a nick... because otherwise their pointer WILL change
136                 // and unless we're lucky we'll get a duff one later on.
137                 //user->dns_done = (!lookup_dns(user->nick));
138                 //if (user->dns_done)
139                 //      ServerInstance->Log(DEBUG,"Aborting dns lookup of %s because dns server experienced a failure.",user->nick);
140
141                 if (ServerInstance->Config->NoUserDns)
142                 {
143                         user->dns_done = true;
144                 }
145                 else
146                 {
147                         user->StartDNSLookup();
148                         if (user->dns_done)
149                                 ServerInstance->Log(DEBUG,"Aborting dns lookup of %s because dns server experienced a failure.",user->nick);
150                 }
151         }
152         if (user->registered == REG_NICKUSER)
153         {
154                 /* user is registered now, bit 0 = USER command, bit 1 = sent a NICK command */
155                 FOREACH_MOD(I_OnUserRegister,OnUserRegister(user));
156                 //ConnectUser(user,NULL);
157         }
158         if (user->registered == REG_ALL)
159         {
160                 FOREACH_MOD(I_OnUserPostNick,OnUserPostNick(user,oldnick));
161         }
162 }