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