]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/message.cpp
Check for duplicate servers in OnLookupComplete
[user/henk/code/inspircd.git] / src / message.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 using namespace std;
18
19 #include "inspircd_config.h"
20 #include "inspircd.h"
21 #include "configreader.h"
22 #include <unistd.h>
23 #include <fcntl.h>
24 #include <sys/errno.h>
25 #include <sys/utsname.h>
26 #include <time.h>
27 #include <string>
28 #include <ext/hash_map>
29 #include <map>
30 #include <sstream>
31 #include <vector>
32 #include <deque>
33 #include "users.h"
34 #include "ctables.h"
35 #include "globals.h"
36 #include "modules.h"
37 #include "dynamic.h"
38 #include "wildcard.h"
39 #include "commands.h"
40 #include "message.h"
41 #include "inspstring.h"
42 #include "dns.h"
43 #include "helperfuncs.h"
44
45 extern int MODCOUNT;
46 extern std::vector<Module*> modules;
47 extern std::vector<ircd_module*> factory;
48 extern time_t TIME;
49 extern ServerConfig* Config;
50
51 /* return 0 or 1 depending if users u and u2 share one or more common channels
52  * (used by QUIT, NICK etc which arent channel specific notices)
53  *
54  * The old algorithm in 1.0 for this was relatively inefficient, iterating over
55  * the first users channels then the second users channels within the outer loop,
56  * therefore it was a maximum of x*y iterations (upon returning 0 and checking
57  * all possible iterations). However this new function instead checks against the
58  * channel's userlist in the inner loop which is a std::map<userrec*,userrec*>
59  * and saves us time as we already know what pointer value we are after.
60  * Don't quote me on the maths as i am not a mathematician or computer scientist,
61  * but i believe this algorithm is now x+(log y) maximum iterations instead.
62  */
63 int common_channels(userrec *u, userrec *u2)
64 {
65         if ((!u) || (!u2) || (u->registered != REG_ALL) || (u2->registered != REG_ALL))
66                 return 0;
67
68         /* Outer loop */
69         for (std::vector<ucrec*>::const_iterator i = u->chans.begin(); i != u->chans.end(); i++)
70         {
71                 /* Fetch the channel from the user */
72                 ucrec* user_channel = *i;
73
74                 if (user_channel->channel)
75                 {
76                         /* Eliminate the inner loop (which used to be ~equal in size to the outer loop)
77                          * by replacing it with a map::find which *should* be more efficient
78                          */
79                         if (user_channel->channel->HasUser(u2))
80                                 return 1;
81                 }
82         }
83         return 0;
84 }
85
86 void Blocking(int s)
87 {
88         int flags = fcntl(s, F_GETFL, 0);
89         fcntl(s, F_SETFL, flags ^ O_NONBLOCK);
90 }
91
92 void NonBlocking(int s)
93 {
94         int flags = fcntl(s, F_GETFL, 0);
95         fcntl(s, F_SETFL, flags | O_NONBLOCK);
96 }
97
98 int CleanAndResolve (char *resolvedHost, const char *unresolvedHost, bool forward, unsigned long timeout)
99 {
100         return 0;
101 }
102
103 int c_count(userrec* u)
104 {
105         int z = 0;
106         for (std::vector<ucrec*>::const_iterator i = u->chans.begin(); i != u->chans.end(); i++)
107                 if ((*i)->channel)
108                         z++;
109         return z;
110
111 }
112
113 void ChangeName(userrec* user, const char* gecos)
114 {
115         if (user->fd > -1)
116         {
117                 int MOD_RESULT = 0;
118                 FOREACH_RESULT(I_OnChangeLocalUserGECOS,OnChangeLocalUserGECOS(user,gecos));
119                 if (MOD_RESULT)
120                         return;
121                 FOREACH_MOD(I_OnChangeName,OnChangeName(user,gecos));
122         }
123         strlcpy(user->fullname,gecos,MAXGECOS+1);
124 }
125
126 void ChangeDisplayedHost(userrec* user, const char* host)
127 {
128         if (user->fd > -1)
129         {
130                 int MOD_RESULT = 0;
131                 FOREACH_RESULT(I_OnChangeLocalUserHost,OnChangeLocalUserHost(user,host));
132                 if (MOD_RESULT)
133                         return;
134                 FOREACH_MOD(I_OnChangeHost,OnChangeHost(user,host));
135         }
136         strlcpy(user->dhost,host,63);
137         WriteServ(user->fd,"396 %s %s :is now your hidden host",user->nick,user->dhost);
138 }
139
140 /* verify that a user's ident and nickname is valid */
141
142 int isident(const char* n)
143 {
144         if (!n || !*n)
145         {
146                 return 0;
147         }
148         for (char* i = (char*)n; *i; i++)
149         {
150                 if ((*i >= 'A') && (*i <= '}'))
151                 {
152                         continue;
153                 }
154                 if (((*i >= '0') && (*i <= '9')) || (*i == '-') || (*i == '.'))
155                 {
156                         continue;
157                 }
158                 return 0;
159         }
160         return 1;
161 }
162
163
164 int isnick(const char* n)
165 {
166         if (!n || !*n)
167         {
168                 return 0;
169         }
170         int p = 0;
171         for (char* i = (char*)n; *i; i++, p++)
172         {
173                 /* "A"-"}" can occur anywhere in a nickname */
174                 if ((*i >= 'A') && (*i <= '}'))
175                 {
176                         continue;
177                 }
178                 /* "0"-"9", "-" can occur anywhere BUT the first char of a nickname */
179                 if ((((*i >= '0') && (*i <= '9')) || (*i == '-')) && (i > n))
180                 {
181                         continue;
182                 }
183                 /* invalid character! abort */
184                 return 0;
185         }
186         return (p < NICKMAX - 1);
187 }
188
189 /* returns the status character for a given user on a channel, e.g. @ for op,
190  * % for halfop etc. If the user has several modes set, the highest mode
191  * the user has must be returned. */
192
193 const char* cmode(userrec *user, chanrec *chan)
194 {
195         if ((!user) || (!chan))
196         {
197                 log(DEFAULT,"*** BUG *** cmode was given an invalid parameter");
198                 return "";
199         }
200
201         for (std::vector<ucrec*>::const_iterator i = user->chans.begin(); i != user->chans.end(); i++)
202         {
203                 if ((*i)->channel == chan)
204                 {
205                         if (((*i)->uc_modes & UCMODE_OP) > 0)
206                         {
207                                 return "@";
208                         }
209                         if (((*i)->uc_modes & UCMODE_HOP) > 0)
210                         {
211                                 return "%";
212                         }
213                         if (((*i)->uc_modes & UCMODE_VOICE) > 0)
214                         {
215                                 return "+";
216                         }
217                         return "";
218                 }
219         }
220         return "";
221 }
222
223 int cflags(userrec *user, chanrec *chan)
224 {
225         if ((!chan) || (!user))
226                 return 0;
227
228         for (std::vector<ucrec*>::const_iterator i = user->chans.begin(); i != user->chans.end(); i++)
229         {
230                 if ((*i)->channel == chan)
231                 {
232                         return (*i)->uc_modes;
233                 }
234         }
235         return 0;
236 }
237
238 /* returns the status value for a given user on a channel, e.g. STATUS_OP for
239  * op, STATUS_VOICE for voice etc. If the user has several modes set, the
240  * highest mode the user has must be returned. */
241
242 int cstatus(userrec *user, chanrec *chan)
243 {
244         if ((!chan) || (!user))
245         {
246                 log(DEFAULT,"*** BUG *** cstatus was given an invalid parameter");
247                 return 0;
248         }
249
250         if (is_uline(user->server))
251                 return STATUS_OP;
252
253         for (std::vector<ucrec*>::const_iterator i = user->chans.begin(); i != user->chans.end(); i++)
254         {
255                 if ((*i)->channel == chan)
256                 {
257                         if (((*i)->uc_modes & UCMODE_OP) > 0)
258                         {
259                                 return STATUS_OP;
260                         }
261                         if (((*i)->uc_modes & UCMODE_HOP) > 0)
262                         {
263                                 return STATUS_HOP;
264                         }
265                         if (((*i)->uc_modes & UCMODE_VOICE) > 0)
266                         {
267                                 return STATUS_VOICE;
268                         }
269                         return STATUS_NORMAL;
270                 }
271         }
272         return STATUS_NORMAL;
273 }
274
275 std::string chlist(userrec *user,userrec* source)
276 {
277         std::string list;
278         
279         if (!user || !source)
280                 return "";
281         
282         for (std::vector<ucrec*>::const_iterator i = user->chans.begin(); i != user->chans.end(); i++)
283         {
284                 ucrec* rec = *i;
285                 
286                 if(rec->channel && rec->channel->name)
287                 {       
288                         /* If the target is the same as the sender, let them see all their channels.
289                          * If the channel is NOT private/secret OR the user shares a common channel
290                          * If the user is an oper, and the <options:operspywhois> option is set.
291                          */
292                         if ((source == user) || (*source->oper && Config->OperSpyWhois) || (((!rec->channel->modes[CM_PRIVATE]) && (!rec->channel->modes[CM_SECRET])) || (rec->channel->HasUser(source))))
293                         {
294                                 list.append(cmode(user, rec->channel)).append(rec->channel->name).append(" ");
295                         }
296                 }
297         }
298         return list;
299 }