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