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