]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/message.cpp
2239916c05598cbea70189b242ddd9588099ce5a
[user/henk/code/inspircd.git] / src / message.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  Inspire is copyright (C) 2002-2004 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 "inspircd.h"
18 #include "inspircd_io.h"
19 #include "inspircd_util.h"
20 #include "inspircd_config.h"
21 #include <unistd.h>
22 #include <fcntl.h>
23 #include <sys/errno.h>
24 #include <sys/ioctl.h>
25 #include <sys/utsname.h>
26 #include <cstdio>
27 #include <time.h>
28 #include <string>
29 #ifdef GCC3
30 #include <ext/hash_map>
31 #else
32 #include <hash_map>
33 #endif
34 #include <map>
35 #include <sstream>
36 #include <vector>
37 #include <errno.h>
38 #include <deque>
39 #include <errno.h>
40 #include <unistd.h>
41 #include <sched.h>
42 #include "connection.h"
43 #include "users.h"
44 #include "servers.h"
45 #include "ctables.h"
46 #include "globals.h"
47 #include "modules.h"
48 #include "dynamic.h"
49 #include "wildcard.h"
50 #include "message.h"
51 #include "inspstring.h"
52
53 using namespace std;
54
55 extern int MODCOUNT;
56 extern std::vector<Module*> modules;
57 extern std::vector<ircd_module*> factory;
58
59 extern time_t TIME;
60
61 /* return 0 or 1 depending if users u and u2 share one or more common channels
62  * (used by QUIT, NICK etc which arent channel specific notices) */
63
64 int common_channels(userrec *u, userrec *u2)
65 {
66         int i = 0;
67         int z = 0;
68
69         if ((!u) || (!u2))
70         {
71                 log(DEFAULT,"*** BUG *** common_channels was given an invalid parameter");
72                 return 0;
73         }
74         for (int i = 0; i != MAXCHANS; i++)
75         {
76                 for (z = 0; z != MAXCHANS; z++)
77                 {
78                         if ((u->chans[i].channel != NULL) && (u2->chans[z].channel != NULL))
79                         {
80                                 if ((!strcasecmp(u->chans[i].channel->name,u2->chans[z].channel->name)) && (u->chans[i].channel) && (u2->chans[z].channel) && (u->registered == 7) && (u2->registered == 7))
81                                 {
82                                         if ((c_count(u)) && (c_count(u2)))
83                                         {
84                                                 return 1;
85                                         }
86                                 }
87                         }
88                 }
89         }
90         return 0;
91 }
92
93
94 void safedelete(userrec *p)
95 {
96         if (p)
97         {
98                 log(DEBUG,"deleting %s %s %s %s",p->nick,p->ident,p->dhost,p->fullname);
99                 log(DEBUG,"safedelete(userrec*): pointer is safe to delete");
100                 delete p;
101                 p = NULL;
102         }
103         else
104         {
105                 log(DEBUG,"safedelete(userrec*): unsafe pointer operation squished");
106         }
107 }
108
109 void safedelete(chanrec *p)
110 {
111         if (p)
112         {
113                 delete p;
114                 p = NULL;
115                 log(DEBUG,"safedelete(chanrec*): pointer is safe to delete");
116         }
117         else
118         {
119                 log(DEBUG,"safedelete(chanrec*): unsafe pointer operation squished");
120         }
121 }
122
123
124 void tidystring(char* str)
125 {
126         // strips out double spaces before a : parameter
127         
128         char temp[MAXBUF];
129         bool go_again = true;
130         
131         if (!str)
132         {
133                 return;
134         }
135         
136         while ((str[0] == ' ') && (strlen(str)>0))
137         {
138                 str++;
139         }
140         
141         while (go_again)
142         {
143                 bool noparse = false;
144                 int t = 0, a = 0;
145                 go_again = false;
146                 while (a < strlen(str))
147                 {
148                         if ((a<strlen(str)-1) && (noparse==false))
149                         {
150                                 if ((str[a] == ' ') && (str[a+1] == ' '))
151                                 {
152                                         log(DEBUG,"Tidied extra space out of string: %s",str);
153                                         go_again = true;
154                                         a++;
155                                 }
156                         }
157                         
158                         if (a<strlen(str)-1)
159                         {
160                                 if ((str[a] == ' ') && (str[a+1] == ':'))
161                                 {
162                                         noparse = true;
163                                 }
164                         }
165                         
166                         temp[t++] = str[a++];
167                 }
168                 temp[t] = '\0';
169                 strlcpy(str,temp,MAXBUF);
170         }
171 }
172
173 /* chop a string down to 512 characters and preserve linefeed (irc max
174  * line length) */
175
176 void chop(char* str)
177 {
178   if (!str)
179   {
180         log(DEBUG,"ERROR! Null string passed to chop()!");
181         return;
182   }
183   string temp = str;
184   FOREACH_MOD OnServerRaw(temp,false,NULL);
185   const char* str2 = temp.c_str();
186   snprintf(str,MAXBUF,"%s",str2);
187   
188
189   if (strlen(str) >= 512)
190   {
191         str[509] = '\r';
192         str[510] = '\n';
193         str[511] = '\0';
194   }
195 }
196
197
198 void Blocking(int s)
199 {
200   int flags;
201   log(DEBUG,"Blocking: %d",s);
202   flags = fcntl(s, F_GETFL, 0);
203   fcntl(s, F_SETFL, flags ^ O_NONBLOCK);
204 }
205
206 void NonBlocking(int s)
207 {
208   int flags;
209   log(DEBUG,"NonBlocking: %d",s);
210   flags = fcntl(s, F_GETFL, 0);
211   //fcntl(s, F_SETFL, O_NONBLOCK);
212   fcntl(s, F_SETFL, flags | O_NONBLOCK);
213 }
214
215 int CleanAndResolve (char *resolvedHost, const char *unresolvedHost)
216 {
217   struct hostent *hostPtr = NULL;
218   struct in_addr addr;
219
220   memset (resolvedHost, '\0',MAXBUF);
221   if(unresolvedHost == NULL)
222         return(ERROR);
223   if ((inet_aton(unresolvedHost,&addr)) == 0)
224         return(ERROR);
225   hostPtr = gethostbyaddr ((char *)&addr.s_addr,sizeof(addr.s_addr),AF_INET);
226   if (hostPtr != NULL)
227         snprintf(resolvedHost,MAXBUF,"%s",hostPtr->h_name);
228   else
229         snprintf(resolvedHost,MAXBUF,"%s",unresolvedHost);
230   return (TRUE);
231 }
232
233 int c_count(userrec* u)
234 {
235         int z = 0;
236         for (int i =0; i != MAXCHANS; i++)
237                 if (u->chans[i].channel != NULL)
238                         z++;
239         return z;
240
241 }
242
243 bool hasumode(userrec* user, char mode)
244 {
245         if (user)
246         {
247                 return (strchr(user->modes,mode)>0);
248         }
249         else return false;
250 }
251
252
253 void ChangeName(userrec* user, const char* gecos)
254 {
255         strlcpy(user->fullname,gecos,MAXBUF);
256         char buffer[MAXBUF];
257         snprintf(buffer,MAXBUF,"a %s :%s",user->nick,gecos);
258         NetSendToAll(buffer);
259 }
260
261 void ChangeDisplayedHost(userrec* user, const char* host)
262 {
263         strlcpy(user->dhost,host,160);
264         char buffer[MAXBUF];
265         snprintf(buffer,MAXBUF,"b %s %s",user->nick,host);
266         NetSendToAll(buffer);
267 }
268
269 /* verify that a user's ident and nickname is valid */
270
271 int isident(const char* n)
272 {
273         char v[MAXBUF];
274         if (!n)
275
276         {
277                 return 0;
278         }
279         if (!strcmp(n,""))
280         {
281                 return 0;
282         }
283         for (int i = 0; i != strlen(n); i++)
284         {
285                 if ((n[i] < 33) || (n[i] > 125))
286                 {
287                         return 0;
288                 }
289                 /* can't occur ANYWHERE in an Ident! */
290                 if (strchr("<>,./?:;@'~#=+()*&%$£ \"!",n[i]))
291                 {
292                         return 0;
293                 }
294         }
295         return 1;
296 }
297
298
299 int isnick(const char* n)
300 {
301         int i = 0;
302         char v[MAXBUF];
303         if (!n)
304         {
305                 return 0;
306         }
307         if (!strcmp(n,""))
308         {
309                 return 0;
310         }
311         if (strlen(n) > NICKMAX-1)
312         {
313                 return 0;
314         }
315         for (int i = 0; i != strlen(n); i++)
316         {
317                 if ((n[i] < 33) || (n[i] > 125))
318                 {
319                         return 0;
320                 }
321                 /* can't occur ANYWHERE in a nickname! */
322                 if (strchr("<>,./?:;@'~#=+()*&%$£ \"!",n[i]))
323                 {
324                         return 0;
325                 }
326                 /* can't occur as the first char of a nickname... */
327                 if ((strchr("0123456789",n[i])) && (!i))
328                 {
329                         return 0;
330                 }
331         }
332         return 1;
333 }
334
335 /* returns the status character for a given user on a channel, e.g. @ for op,
336  * % for halfop etc. If the user has several modes set, the highest mode
337  * the user has must be returned. */
338
339 char* cmode(userrec *user, chanrec *chan)
340 {
341         if ((!user) || (!chan))
342         {
343                 log(DEFAULT,"*** BUG *** cmode was given an invalid parameter");
344                 return "";
345         }
346
347         int i;
348         for (int i = 0; i != MAXCHANS; i++)
349         {
350                 if (user->chans[i].channel)
351                 {
352                         if ((!strcasecmp(user->chans[i].channel->name,chan->name)) && (chan != NULL))
353                         {
354                                 if ((user->chans[i].uc_modes & UCMODE_OP) > 0)
355                                 {
356                                         return "@";
357                                 }
358                                 if ((user->chans[i].uc_modes & UCMODE_HOP) > 0)
359                                 {
360                                         return "%";
361                                 }
362                                 if ((user->chans[i].uc_modes & UCMODE_VOICE) > 0)
363                                 {
364                                         return "+";
365                                 }
366                                 return "";
367                         }
368                 }
369         }
370 }
371
372 /* returns the status value for a given user on a channel, e.g. STATUS_OP for
373  * op, STATUS_VOICE for voice etc. If the user has several modes set, the
374  * highest mode the user has must be returned. */
375
376 int cstatus(userrec *user, chanrec *chan)
377 {
378         if ((!chan) || (!user))
379         {
380                 log(DEFAULT,"*** BUG *** cstatus was given an invalid parameter");
381                 return 0;
382         }
383
384         for (int i = 0; i != MAXCHANS; i++)
385         {
386                 if (user->chans[i].channel)
387                 {
388                         if ((!strcasecmp(user->chans[i].channel->name,chan->name)) && (chan != NULL))
389                         {
390                                 if ((user->chans[i].uc_modes & UCMODE_OP) > 0)
391                                 {
392                                         return STATUS_OP;
393                                 }
394                                 if ((user->chans[i].uc_modes & UCMODE_HOP) > 0)
395                                 {
396                                         return STATUS_HOP;
397                                 }
398                                 if ((user->chans[i].uc_modes & UCMODE_VOICE) > 0)
399                                 {
400                                         return STATUS_VOICE;
401                                 }
402                                 return STATUS_NORMAL;
403                         }
404                 }
405         }
406 }
407
408 /* returns 1 if user u has channel c in their record, 0 if not */
409
410 int has_channel(userrec *u, chanrec *c)
411 {
412         if ((!u) || (!c))
413         {
414                 log(DEFAULT,"*** BUG *** has_channel was given an invalid parameter");
415                 return 0;
416         }
417         for (int i =0; i != MAXCHANS; i++)
418         {
419                 if (u->chans[i].channel)
420                 {
421                         if (!strcasecmp(u->chans[i].channel->name,c->name))
422                         {
423                                 return 1;
424                         }
425                 }
426         }
427         return 0;
428 }
429
430
431 void TidyBan(char *ban)
432 {
433         if (!ban) {
434                 log(DEFAULT,"*** BUG *** TidyBan was given an invalid parameter");
435                 return;
436         }
437         
438         char temp[MAXBUF],NICK[MAXBUF],IDENT[MAXBUF],HOST[MAXBUF];
439
440         strlcpy(temp,ban,MAXBUF);
441
442         char* pos_of_pling = strchr(temp,'!');
443         char* pos_of_at = strchr(temp,'@');
444
445         pos_of_pling[0] = '\0';
446         pos_of_at[0] = '\0';
447         pos_of_pling++;
448         pos_of_at++;
449
450         strlcpy(NICK,temp,NICKMAX);
451         strlcpy(IDENT,pos_of_pling,IDENTMAX+1);
452         strlcpy(HOST,pos_of_at,160);
453
454         snprintf(ban,MAXBUF,"%s!%s@%s",NICK,IDENT,HOST);
455 }
456
457 char lst[MAXBUF];
458
459 char* chlist(userrec *user)
460 {
461         int i = 0;
462         char cmp[MAXBUF];
463
464         log(DEBUG,"chlist: %s",user->nick);
465         strcpy(lst,"");
466         if (!user)
467         {
468                 return lst;
469         }
470         for (int i = 0; i != MAXCHANS; i++)
471         {
472                 if (user->chans[i].channel != NULL)
473                 {
474                         if (user->chans[i].channel->name)
475                         {
476                                 strlcpy(cmp,user->chans[i].channel->name,MAXBUF);
477                                 strlcat(cmp," ",MAXBUF);
478                                 if (!strstr(lst,cmp))
479                                 {
480                                         if ((!user->chans[i].channel->c_private) && (!user->chans[i].channel->secret))
481                                         {
482                                                 strlcat(lst,cmode(user,user->chans[i].channel),MAXBUF);
483                                                 strlcat(lst,user->chans[i].channel->name,MAXBUF);
484                                                 strlcat(lst," ",MAXBUF);
485                                         }
486                                 }
487                         }
488                 }
489         }
490         if (strlen(lst))
491         {
492                 lst[strlen(lst)-1] = '\0'; // chop trailing space
493         }
494         return lst;
495 }
496
497
498 void send_network_quit(const char* nick, const char* reason)
499 {
500         char buffer[MAXBUF];
501         snprintf(buffer,MAXBUF,"Q %s :%s",nick,reason);
502         NetSendToAll(buffer);
503 }
504
505