]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/message.cpp
(1) remove CleanAndResolve.
[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 c_count(userrec* u)
99 {
100         int z = 0;
101         for (std::vector<ucrec*>::const_iterator i = u->chans.begin(); i != u->chans.end(); i++)
102                 if ((*i)->channel)
103                         z++;
104         return z;
105
106 }
107
108 void ChangeName(userrec* user, const char* gecos)
109 {
110         if (user->fd > -1)
111         {
112                 int MOD_RESULT = 0;
113                 FOREACH_RESULT(I_OnChangeLocalUserGECOS,OnChangeLocalUserGECOS(user,gecos));
114                 if (MOD_RESULT)
115                         return;
116                 FOREACH_MOD(I_OnChangeName,OnChangeName(user,gecos));
117         }
118         strlcpy(user->fullname,gecos,MAXGECOS+1);
119 }
120
121 void ChangeDisplayedHost(userrec* user, const char* host)
122 {
123         if (user->fd > -1)
124         {
125                 int MOD_RESULT = 0;
126                 FOREACH_RESULT(I_OnChangeLocalUserHost,OnChangeLocalUserHost(user,host));
127                 if (MOD_RESULT)
128                         return;
129                 FOREACH_MOD(I_OnChangeHost,OnChangeHost(user,host));
130         }
131         strlcpy(user->dhost,host,63);
132         WriteServ(user->fd,"396 %s %s :is now your hidden host",user->nick,user->dhost);
133 }
134
135 /* verify that a user's ident and nickname is valid */
136
137 int isident(const char* n)
138 {
139         if (!n || !*n)
140         {
141                 return 0;
142         }
143         for (char* i = (char*)n; *i; i++)
144         {
145                 if ((*i >= 'A') && (*i <= '}'))
146                 {
147                         continue;
148                 }
149                 if (((*i >= '0') && (*i <= '9')) || (*i == '-') || (*i == '.'))
150                 {
151                         continue;
152                 }
153                 return 0;
154         }
155         return 1;
156 }
157
158
159 int isnick(const char* n)
160 {
161         if (!n || !*n)
162         {
163                 return 0;
164         }
165         int p = 0;
166         for (char* i = (char*)n; *i; i++, p++)
167         {
168                 /* "A"-"}" can occur anywhere in a nickname */
169                 if ((*i >= 'A') && (*i <= '}'))
170                 {
171                         continue;
172                 }
173                 /* "0"-"9", "-" can occur anywhere BUT the first char of a nickname */
174                 if ((((*i >= '0') && (*i <= '9')) || (*i == '-')) && (i > n))
175                 {
176                         continue;
177                 }
178                 /* invalid character! abort */
179                 return 0;
180         }
181         return (p < NICKMAX - 1);
182 }
183
184 /* returns the status character for a given user on a channel, e.g. @ for op,
185  * % for halfop etc. If the user has several modes set, the highest mode
186  * the user has must be returned. */
187
188 const char* cmode(userrec *user, chanrec *chan)
189 {
190         if ((!user) || (!chan))
191         {
192                 log(DEFAULT,"*** BUG *** cmode was given an invalid parameter");
193                 return "";
194         }
195
196         for (std::vector<ucrec*>::const_iterator i = user->chans.begin(); i != user->chans.end(); i++)
197         {
198                 if ((*i)->channel == chan)
199                 {
200                         if (((*i)->uc_modes & UCMODE_OP) > 0)
201                         {
202                                 return "@";
203                         }
204                         if (((*i)->uc_modes & UCMODE_HOP) > 0)
205                         {
206                                 return "%";
207                         }
208                         if (((*i)->uc_modes & UCMODE_VOICE) > 0)
209                         {
210                                 return "+";
211                         }
212                         return "";
213                 }
214         }
215         return "";
216 }
217
218 int cflags(userrec *user, chanrec *chan)
219 {
220         if ((!chan) || (!user))
221                 return 0;
222
223         for (std::vector<ucrec*>::const_iterator i = user->chans.begin(); i != user->chans.end(); i++)
224         {
225                 if ((*i)->channel == chan)
226                 {
227                         return (*i)->uc_modes;
228                 }
229         }
230         return 0;
231 }
232
233 /* returns the status value for a given user on a channel, e.g. STATUS_OP for
234  * op, STATUS_VOICE for voice etc. If the user has several modes set, the
235  * highest mode the user has must be returned. */
236
237 int cstatus(userrec *user, chanrec *chan)
238 {
239         if ((!chan) || (!user))
240         {
241                 log(DEFAULT,"*** BUG *** cstatus was given an invalid parameter");
242                 return 0;
243         }
244
245         if (is_uline(user->server))
246                 return STATUS_OP;
247
248         for (std::vector<ucrec*>::const_iterator i = user->chans.begin(); i != user->chans.end(); i++)
249         {
250                 if ((*i)->channel == chan)
251                 {
252                         if (((*i)->uc_modes & UCMODE_OP) > 0)
253                         {
254                                 return STATUS_OP;
255                         }
256                         if (((*i)->uc_modes & UCMODE_HOP) > 0)
257                         {
258                                 return STATUS_HOP;
259                         }
260                         if (((*i)->uc_modes & UCMODE_VOICE) > 0)
261                         {
262                                 return STATUS_VOICE;
263                         }
264                         return STATUS_NORMAL;
265                 }
266         }
267         return STATUS_NORMAL;
268 }
269
270 std::string chlist(userrec *user,userrec* source)
271 {
272         std::string list;
273         
274         if (!user || !source)
275                 return "";
276         
277         for (std::vector<ucrec*>::const_iterator i = user->chans.begin(); i != user->chans.end(); i++)
278         {
279                 ucrec* rec = *i;
280                 
281                 if(rec->channel && rec->channel->name)
282                 {       
283                         /* If the target is the same as the sender, let them see all their channels.
284                          * If the channel is NOT private/secret OR the user shares a common channel
285                          * If the user is an oper, and the <options:operspywhois> option is set.
286                          */
287                         if ((source == user) || (*source->oper && Config->OperSpyWhois) || (((!rec->channel->modes[CM_PRIVATE]) && (!rec->channel->modes[CM_SECRET])) || (rec->channel->HasUser(source))))
288                         {
289                                 list.append(cmode(user, rec->channel)).append(rec->channel->name).append(" ");
290                         }
291                 }
292         }
293         return list;
294 }