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