]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/mode.cpp
added mode.h/mode.cpp and seperated mode functions into it
[user/henk/code/inspircd.git] / src / mode.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 extern int LogLevel;
41 extern char ServerName[MAXBUF];
42 extern char Network[MAXBUF];
43 extern char ServerDesc[MAXBUF];
44 extern char AdminName[MAXBUF];
45 extern char AdminEmail[MAXBUF];
46 extern char AdminNick[MAXBUF];
47 extern char diepass[MAXBUF];
48 extern char restartpass[MAXBUF];
49 extern char motd[MAXBUF];
50 extern char rules[MAXBUF];
51 extern char list[MAXBUF];
52 extern char PrefixQuit[MAXBUF];
53 extern char DieValue[MAXBUF];
54
55 int give_ops(userrec *user,char *dest,chanrec *chan,int status)
56 {
57         userrec *d;
58         int i;
59         
60         if ((!user) || (!dest) || (!chan))
61         {
62                 log(DEFAULT,"*** BUG *** give_ops was given an invalid parameter");
63                 return 0;
64         }
65         if (status < STATUS_OP)
66         {
67                 log(DEBUG,"%s cant give ops to %s because they nave status %d and needs %d",user->nick,dest,status,STATUS_OP);
68                 WriteServ(user->fd,"482 %s %s :You're not a channel operator",user->nick, chan->name);
69                 return 0;
70         }
71         else
72         {
73                 if (!isnick(dest))
74                 {
75                         log(DEFAULT,"the target nickname given to give_ops was invalid");
76                         WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest);
77                         return 0;
78                 }
79                 d = Find(dest);
80                 if (!d)
81                 {
82                         log(DEFAULT,"the target nickname given to give_ops couldnt be found");
83                         WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest);
84                         return 0;
85                 }
86                 else
87                 {
88                         for (int i = 0; i != MAXCHANS; i++)
89                         {
90                                 if ((d->chans[i].channel != NULL) && (chan != NULL))
91                                 if (!strcasecmp(d->chans[i].channel->name,chan->name))
92                                 {
93                                         if (d->chans[i].uc_modes & UCMODE_OP)
94                                         {
95                                                 /* mode already set on user, dont allow multiple */
96                                                 log(DEFAULT,"The target user given to give_ops was already opped on the channel");
97                                                 return 0;
98                                         }
99                                         d->chans[i].uc_modes = d->chans[i].uc_modes | UCMODE_OP;
100                                         log(DEBUG,"gave ops: %s %s",d->chans[i].channel->name,d->nick);
101                                         return 1;
102                                 }
103                         }
104                         log(DEFAULT,"The target channel given to give_ops was not in the users mode list");
105                 }
106         }
107         return 1;
108 }
109
110 int give_hops(userrec *user,char *dest,chanrec *chan,int status)
111 {
112         userrec *d;
113         int i;
114         
115         if ((!user) || (!dest) || (!chan))
116         {
117                 log(DEFAULT,"*** BUG *** give_hops was given an invalid parameter");
118                 return 0;
119         }
120         if (status != STATUS_OP)
121         {
122                 WriteServ(user->fd,"482 %s %s :You're not a channel operator",user->nick, chan->name);
123                 return 0;
124         }
125         else
126         {
127                 d = Find(dest);
128                 if (!isnick(dest))
129                 {
130                         WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest);
131                         return 0;
132                 }
133                 if (!d)
134                 {
135                         WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest);
136                         return 0;
137                 }
138                 else
139                 {
140                         for (int i = 0; i != MAXCHANS; i++)
141                         {
142                                 if ((d->chans[i].channel != NULL) && (chan != NULL))
143                                 if (!strcasecmp(d->chans[i].channel->name,chan->name))
144                                 {
145                                         if (d->chans[i].uc_modes & UCMODE_HOP)
146                                         {
147                                                 /* mode already set on user, dont allow multiple */
148                                                 return 0;
149                                         }
150                                         d->chans[i].uc_modes = d->chans[i].uc_modes | UCMODE_HOP;
151                                         log(DEBUG,"gave h-ops: %s %s",d->chans[i].channel->name,d->nick);
152                                         return 1;
153                                 }
154                         }
155                 }
156         }
157         return 1;
158 }
159
160 int give_voice(userrec *user,char *dest,chanrec *chan,int status)
161 {
162         userrec *d;
163         int i;
164         
165         if ((!user) || (!dest) || (!chan))
166         {
167                 log(DEFAULT,"*** BUG *** give_voice was given an invalid parameter");
168                 return 0;
169         }
170         if (status < STATUS_HOP)
171         {
172                 WriteServ(user->fd,"482 %s %s :You must be at least a half-operator to change modes on this channel",user->nick, chan->name);
173                 return 0;
174         }
175         else
176         {
177                 d = Find(dest);
178                 if (!isnick(dest))
179                 {
180                         WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest);
181                         return 0;
182                 }
183                 if (!d)
184                 {
185                         WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest);
186                         return 0;
187                 }
188                 else
189                 {
190                         for (int i = 0; i != MAXCHANS; i++)
191                         {
192                                 if ((d->chans[i].channel != NULL) && (chan != NULL))
193                                 if (!strcasecmp(d->chans[i].channel->name,chan->name))
194                                 {
195                                         if (d->chans[i].uc_modes & UCMODE_VOICE)
196                                         {
197                                                 /* mode already set on user, dont allow multiple */
198                                                 return 0;
199                                         }
200                                         d->chans[i].uc_modes = d->chans[i].uc_modes | UCMODE_VOICE;
201                                         log(DEBUG,"gave voice: %s %s",d->chans[i].channel->name,d->nick);
202                                         return 1;
203                                 }
204                         }
205                 }
206         }
207         return 1;
208 }
209
210 int take_ops(userrec *user,char *dest,chanrec *chan,int status)
211 {
212         userrec *d;
213         int i;
214         
215         if ((!user) || (!dest) || (!chan))
216         {
217                 log(DEFAULT,"*** BUG *** take_ops was given an invalid parameter");
218                 return 0;
219         }
220         if (status < STATUS_OP)
221         {
222                 log(DEBUG,"%s cant give ops to %s because they have status %d and needs %d",user->nick,dest,status,STATUS_OP);
223                 WriteServ(user->fd,"482 %s %s :You're not a channel operator",user->nick, chan->name);
224                 return 0;
225         }
226         else
227         {
228                 d = Find(dest);
229                 if (!isnick(dest))
230                 {
231                         log(DEBUG,"take_ops was given an invalid target nickname of %s",dest);
232                         WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest);
233                         return 0;
234                 }
235                 if (!d)
236                 {
237                         log(DEBUG,"take_ops couldnt resolve the target nickname: %s",dest);
238                         WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest);
239                         return 0;
240                 }
241                 else
242                 {
243                         for (int i = 0; i != MAXCHANS; i++)
244                         {
245                                 if ((d->chans[i].channel != NULL) && (chan != NULL))
246                                 if (!strcasecmp(d->chans[i].channel->name,chan->name))
247                                 {
248                                         if ((d->chans[i].uc_modes & UCMODE_OP) == 0)
249                                         {
250                                                 /* mode already set on user, dont allow multiple */
251                                                 return 0;
252                                         }
253                                         d->chans[i].uc_modes ^= UCMODE_OP;
254                                         log(DEBUG,"took ops: %s %s",d->chans[i].channel->name,d->nick);
255                                         return 1;
256                                 }
257                         }
258                         log(DEBUG,"take_ops couldnt locate the target channel in the target users list");
259                 }
260         }
261         return 1;
262 }
263
264 int take_hops(userrec *user,char *dest,chanrec *chan,int status)
265 {
266         userrec *d;
267         int i;
268         
269         if ((!user) || (!dest) || (!chan))
270         {
271                 log(DEFAULT,"*** BUG *** take_hops was given an invalid parameter");
272                 return 0;
273         }
274         if (status != STATUS_OP)
275         {
276                 WriteServ(user->fd,"482 %s %s :You're not a channel operator",user->nick, chan->name);
277                 return 0;
278         }
279         else
280         {
281                 d = Find(dest);
282                 if (!isnick(dest))
283                 {
284                         WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest);
285                         return 0;
286                 }
287                 if (!d)
288                 {
289                         WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest);
290                         return 0;
291                 }
292                 else
293                 {
294                         for (int i = 0; i != MAXCHANS; i++)
295                         {
296                                 if ((d->chans[i].channel != NULL) && (chan != NULL))
297                                 if (!strcasecmp(d->chans[i].channel->name,chan->name))
298                                 {
299                                         if ((d->chans[i].uc_modes & UCMODE_HOP) == 0)
300                                         {
301                                                 /* mode already set on user, dont allow multiple */
302                                                 return 0;
303                                         }
304                                         d->chans[i].uc_modes ^= UCMODE_HOP;
305                                         log(DEBUG,"took h-ops: %s %s",d->chans[i].channel->name,d->nick);
306                                         return 1;
307                                 }
308                         }
309                 }
310         }
311         return 1;
312 }
313
314 int take_voice(userrec *user,char *dest,chanrec *chan,int status)
315 {
316         userrec *d;
317         int i;
318         
319         if ((!user) || (!dest) || (!chan))
320         {
321                 log(DEFAULT,"*** BUG *** take_voice was given an invalid parameter");
322                 return 0;
323         }
324         if (status < STATUS_HOP)
325         {
326                 WriteServ(user->fd,"482 %s %s :You must be at least a half-operator to change modes on this channel",user->nick, chan->name);
327                 return 0;
328         }
329         else
330         {
331                 d = Find(dest);
332                 if (!isnick(dest))
333                 {
334                         WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest);
335                         return 0;
336                 }
337                 if (!d)
338                 {
339                         WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest);
340                         return 0;
341                 }
342                 else
343                 {
344                         for (int i = 0; i != MAXCHANS; i++)
345                         {
346                                 if ((d->chans[i].channel != NULL) && (chan != NULL))
347                                 if (!strcasecmp(d->chans[i].channel->name,chan->name))
348                                 {
349                                         if ((d->chans[i].uc_modes & UCMODE_VOICE) == 0)
350                                         {
351                                                 /* mode already set on user, dont allow multiple */
352                                                 return 0;
353                                         }
354                                         d->chans[i].uc_modes ^= UCMODE_VOICE;
355                                         log(DEBUG,"took voice: %s %s",d->chans[i].channel->name,d->nick);
356                                         return 1;
357                                 }
358                         }
359                 }
360         }
361         return 1;
362 }
363
364 int add_ban(userrec *user,char *dest,chanrec *chan,int status)
365 {
366         if ((!user) || (!dest) || (!chan)) {
367                 log(DEFAULT,"*** BUG *** add_ban was given an invalid parameter");
368                 return 0;
369         }
370
371         BanItem b;
372         if ((!user) || (!dest) || (!chan))
373                 return 0;
374         if (strchr(dest,'!')==0)
375                 return 0;
376         if (strchr(dest,'@')==0)
377                 return 0;
378         for (int i = 0; i < strlen(dest); i++)
379                 if (dest[i] < 32)
380                         return 0;
381         for (int i = 0; i < strlen(dest); i++)
382                 if (dest[i] > 126)
383                         return 0;
384         int c = 0;
385         for (int i = 0; i < strlen(dest); i++)
386                 if (dest[i] == '!')
387                         c++;
388         if (c>1)
389                 return 0;
390         c = 0;
391         for (int i = 0; i < strlen(dest); i++)
392                 if (dest[i] == '@')
393                         c++;
394         if (c>1)
395                 return 0;
396         log(DEBUG,"add_ban: %s %s",chan->name,user->nick);
397
398         TidyBan(dest);
399         for (BanList::iterator i = chan->bans.begin(); i != chan->bans.end(); i++)
400         {
401                 if (!strcasecmp(i->data,dest))
402                 {
403                         // dont allow a user to set the same ban twice
404                         return 0;
405                 }
406         }
407
408         b.set_time = time(NULL);
409         strncpy(b.data,dest,MAXBUF);
410         strncpy(b.set_by,user->nick,NICKMAX);
411         chan->bans.push_back(b);
412         return 1;
413 }
414
415 int take_ban(userrec *user,char *dest,chanrec *chan,int status)
416 {
417         if ((!user) || (!dest) || (!chan)) {
418                 log(DEFAULT,"*** BUG *** take_ban was given an invalid parameter");
419                 return 0;
420         }
421
422         log(DEBUG,"del_ban: %s %s",chan->name,user->nick);
423         for (BanList::iterator i = chan->bans.begin(); i != chan->bans.end(); i++)
424         {
425                 if (!strcasecmp(i->data,dest))
426                 {
427                         chan->bans.erase(i);
428                         return 1;
429                 }
430         }
431         return 0;
432 }
433
434 void process_modes(char **parameters,userrec* user,chanrec *chan,int status, int pcnt, bool servermode, bool silent, bool local)
435 {
436         if (!parameters) {
437                 log(DEFAULT,"*** BUG *** process_modes was given an invalid parameter");
438                 return;
439         }
440
441         char modelist[MAXBUF];
442         char outlist[MAXBUF];
443         char outstr[MAXBUF];
444         char outpars[32][MAXBUF];
445         int param = 2;
446         int pc = 0;
447         int ptr = 0;
448         int mdir = 1;
449         int r = 0;
450         bool k_set = false, l_set = false;
451
452         if (pcnt < 2)
453         {
454                 return;
455         }
456
457         log(DEBUG,"process_modes: start: parameters=%d",pcnt);
458
459         strcpy(modelist,parameters[1]); /* mode list, e.g. +oo-o */
460                                         /* parameters[2] onwards are parameters for
461                                          * modes that require them :) */
462         strcpy(outlist,"+");
463         mdir = 1;
464
465         log(DEBUG,"process_modes: modelist: %s",modelist);
466
467         for (ptr = 0; ptr < strlen(modelist); ptr++)
468         {
469                 r = 0;
470
471                 {
472                         log(DEBUG,"process_modes: modechar: %c",modelist[ptr]);
473                         char modechar = modelist[ptr];
474                         switch (modelist[ptr])
475                         {
476                                 case '-':
477                                         if (mdir != 0)
478                                         {
479                                                 if ((outlist[strlen(outlist)-1] == '+') || (outlist[strlen(outlist)-1] == '-'))
480                                                 {
481                                                         outlist[strlen(outlist)-1] = '-';
482                                                 }
483                                                 else
484                                                 {
485                                                         strcat(outlist,"-");
486                                                 }
487                                         }
488                                         mdir = 0;
489                                         
490                                 break;                  
491
492                                 case '+':
493                                         if (mdir != 1)
494                                         {
495                                                 if ((outlist[strlen(outlist)-1] == '+') || (outlist[strlen(outlist)-1] == '-'))
496                                                 {
497                                                         outlist[strlen(outlist)-1] = '+';
498                                                 }
499                                                 else
500                                                 {
501                                                         strcat(outlist,"+");
502                                                 }
503                                         }
504                                         mdir = 1;
505                                 break;
506
507                                 case 'o':
508                                         log(DEBUG,"Ops");
509                                         if ((param >= pcnt)) break;
510                                         log(DEBUG,"Enough parameters left");
511                                         if (mdir == 1)
512                                         {
513                                                 log(DEBUG,"calling give_ops");
514                                                 r = give_ops(user,parameters[param++],chan,status);
515                                         }
516                                         else
517                                         {
518                                                 log(DEBUG,"calling take_ops");
519                                                 r = take_ops(user,parameters[param++],chan,status);
520                                         }
521                                         if (r)
522                                         {
523                                                 strcat(outlist,"o");
524                                                 strcpy(outpars[pc++],parameters[param-1]);
525                                         }
526                                 break;
527                         
528                                 case 'h':
529                                         if ((param >= pcnt)) break;
530                                         if (mdir == 1)
531                                         {
532                                                 r = give_hops(user,parameters[param++],chan,status);
533                                         }
534                                         else
535                                         {
536                                                 r = take_hops(user,parameters[param++],chan,status);
537                                         }
538                                         if (r)
539                                         {
540                                                 strcat(outlist,"h");
541                                                 strcpy(outpars[pc++],parameters[param-1]);
542                                         }
543                                 break;
544                         
545                                 
546                                 case 'v':
547                                         if ((param >= pcnt)) break;
548                                         if (mdir == 1)
549                                         {
550                                                 r = give_voice(user,parameters[param++],chan,status);
551                                         }
552                                         else
553                                         {
554                                                 r = take_voice(user,parameters[param++],chan,status);
555                                         }
556                                         if (r)
557                                         {
558                                                 strcat(outlist,"v");
559                                                 strcpy(outpars[pc++],parameters[param-1]);
560                                         }
561                                 break;
562                                 
563                                 case 'b':
564                                         if ((param >= pcnt)) break;
565                                         if (mdir == 1)
566                                         {
567                                                 r = add_ban(user,parameters[param++],chan,status);
568                                         }
569                                         else
570                                         {
571                                                 r = take_ban(user,parameters[param++],chan,status);
572                                         }
573                                         if (r)
574                                         {
575                                                 strcat(outlist,"b");
576                                                 strcpy(outpars[pc++],parameters[param-1]);
577                                         }
578                                 break;
579
580
581                                 case 'k':
582                                         if ((param >= pcnt))
583                                                 break;
584
585                                         if (mdir == 1)
586                                         {
587                                                 if (k_set)
588                                                         break;
589                                                 
590                                                 if (!strcmp(chan->key,""))
591                                                 {
592                                                         strcat(outlist,"k");
593                                                         char key[MAXBUF];
594                                                         strcpy(key,parameters[param++]);
595                                                         if (strlen(key)>32) {
596                                                                 key[31] = '\0';
597                                                         }
598                                                         strcpy(outpars[pc++],key);
599                                                         strcpy(chan->key,key);
600                                                         k_set = true;
601                                                 }
602                                         }
603                                         else
604                                         {
605                                                 /* checks on -k are case sensitive and only accurate to the
606                                                    first 32 characters */
607                                                 char key[MAXBUF];
608                                                 strcpy(key,parameters[param++]);
609                                                 if (strlen(key)>32) {
610                                                         key[31] = '\0';
611                                                 }
612                                                 /* only allow -k if correct key given */
613                                                 if (!strcmp(chan->key,key))
614                                                 {
615                                                         strcat(outlist,"k");
616                                                         strcpy(chan->key,"");
617                                                         strcpy(outpars[pc++],key);
618                                                 }
619                                         }
620                                 break;
621                                 
622                                 case 'l':
623                                         if (mdir == 0)
624                                         {
625                                                 if (chan->limit)
626                                                 {
627                                                         strcat(outlist,"l");
628                                                         chan->limit = 0;
629                                                 }
630                                         }
631                                         
632                                         if ((param >= pcnt)) break;
633                                         if (mdir == 1)
634                                         {
635                                                 if (l_set)
636                                                         break;
637                                                 
638                                                 bool invalid = false;
639                                                 for (int i = 0; i < strlen(parameters[param]); i++)
640                                                 {
641                                                         if ((parameters[param][i] < '0') || (parameters[param][i] > '9'))
642                                                         {
643                                                                 invalid = true;
644                                                         }
645                                                 }
646                                                 if (atoi(parameters[param]) < 1)
647                                                 {
648                                                         invalid = true;
649                                                 }
650
651                                                 if (invalid)
652                                                         break;
653                                                 
654                                                 chan->limit = atoi(parameters[param]);
655                                                 if (chan->limit)
656                                                 {
657                                                         strcat(outlist,"l");
658                                                         strcpy(outpars[pc++],parameters[param++]);
659                                                         l_set = true;
660                                                 }
661                                         }
662                                 break;
663                                 
664                                 case 'i':
665                                         if (chan->inviteonly != mdir)
666                                         {
667                                                 strcat(outlist,"i");
668                                         }
669                                         chan->inviteonly = mdir;
670                                 break;
671                                 
672                                 case 't':
673                                         if (chan->topiclock != mdir)
674                                         {
675                                                 strcat(outlist,"t");
676                                         }
677                                         chan->topiclock = mdir;
678                                 break;
679                                 
680                                 case 'n':
681                                         if (chan->noexternal != mdir)
682                                         {
683                                                 strcat(outlist,"n");
684                                         }
685                                         chan->noexternal = mdir;
686                                 break;
687                                 
688                                 case 'm':
689                                         if (chan->moderated != mdir)
690                                         {
691                                                 strcat(outlist,"m");
692                                         }
693                                         chan->moderated = mdir;
694                                 break;
695                                 
696                                 case 's':
697                                         if (chan->secret != mdir)
698                                         {
699                                                 strcat(outlist,"s");
700                                                 if (chan->c_private)
701                                                 {
702                                                         chan->c_private = 0;
703                                                         if (mdir)
704                                                         {
705                                                                 strcat(outlist,"-p+");
706                                                         }
707                                                         else
708                                                         {
709                                                                 strcat(outlist,"+p-");
710                                                         }
711                                                 }
712                                         }
713                                         chan->secret = mdir;
714                                 break;
715                                 
716                                 case 'p':
717                                         if (chan->c_private != mdir)
718                                         {
719                                                 strcat(outlist,"p");
720                                                 if (chan->secret)
721                                                 {
722                                                         chan->secret = 0;
723                                                         if (mdir)
724                                                         {
725                                                                 strcat(outlist,"-s+");
726                                                         }
727                                                         else
728                                                         {
729                                                                 strcat(outlist,"+s-");
730                                                         }
731                                                 }
732                                         }
733                                         chan->c_private = mdir;
734                                 break;
735                                 
736                                 default:
737                                         log(DEBUG,"Preprocessing custom mode %c",modechar);
738                                         string_list p;
739                                         p.clear();
740                                         if (((!strchr(chan->custom_modes,modechar)) && (!mdir)) || ((strchr(chan->custom_modes,modechar)) && (mdir)))
741                                         {
742                                                 log(DEBUG,"Mode %c isnt set on %s but trying to remove!",modechar,chan->name);
743                                                 break;
744                                         }
745                                         if (ModeDefined(modechar,MT_CHANNEL))
746                                         {
747                                                 log(DEBUG,"A module has claimed this mode");
748                                                 if (param<pcnt)
749                                                 {
750                                                         if ((ModeDefinedOn(modechar,MT_CHANNEL)>0) && (mdir))
751                                                         {
752                                                                 p.push_back(parameters[param]);
753                                                         }
754                                                         if ((ModeDefinedOff(modechar,MT_CHANNEL)>0) && (!mdir))
755                                                         {
756                                                                 p.push_back(parameters[param]);
757                                                         }
758                                                 }
759                                                 bool handled = false;
760                                                 if (param>=pcnt)
761                                                 {
762                                                         log(DEBUG,"Not enough parameters for module-mode %c",modechar);
763                                                         // we're supposed to have a parameter, but none was given... so dont handle the mode.
764                                                         if (((ModeDefinedOn(modechar,MT_CHANNEL)>0) && (mdir)) || ((ModeDefinedOff(modechar,MT_CHANNEL)>0) && (!mdir))) 
765                                                         {
766                                                                 handled = true;
767                                                                 param++;
768                                                         }
769                                                 }
770                                                 for (int i = 0; i <= MODCOUNT; i++)
771                                                 {
772                                                         if (!handled)
773                                                         {
774                                                                 if (modules[i]->OnExtendedMode(user,chan,modechar,MT_CHANNEL,mdir,p))
775                                                                 {
776                                                                         log(DEBUG,"OnExtendedMode returned nonzero for a module");
777                                                                         char app[] = {modechar, 0};
778                                                                         if (ptr>0)
779                                                                         {
780                                                                                 if ((modelist[ptr-1] == '+') || (modelist[ptr-1] == '-'))
781                                                                                 {
782                                                                                         strcat(outlist, app);
783                                                                                 }
784                                                                                 else if (!strchr(outlist,modechar))
785                                                                                 {
786                                                                                         strcat(outlist, app);
787                                                                                 }
788                                                                         }
789                                                                         chan->SetCustomMode(modechar,mdir);
790                                                                         // include parameters in output if mode has them
791                                                                         if ((ModeDefinedOn(modechar,MT_CHANNEL)>0) && (mdir))
792                                                                         {
793                                                                                 chan->SetCustomModeParam(modelist[ptr],parameters[param],mdir);
794                                                                                 strcpy(outpars[pc++],parameters[param++]);
795                                                                         }
796                                                                         // break, because only one module can handle the mode.
797                                                                         handled = true;
798                                                                 }
799                                                         }
800                                                 }
801                                         }
802                                 break;
803                                 
804                         }
805                 }
806         }
807
808         /* this ensures only the *valid* modes are sent out onto the network */
809         while ((outlist[strlen(outlist)-1] == '-') || (outlist[strlen(outlist)-1] == '+'))
810         {
811                 outlist[strlen(outlist)-1] = '\0';
812         }
813         if (strcmp(outlist,""))
814         {
815                 strcpy(outstr,outlist);
816                 for (ptr = 0; ptr < pc; ptr++)
817                 {
818                         strcat(outstr," ");
819                         strcat(outstr,outpars[ptr]);
820                 }
821                 if (local)
822                 {
823                         log(DEBUG,"Local mode change");
824                         WriteChannelLocal(chan, user, "MODE %s %s",chan->name,outstr);
825                 }
826                 else
827                 {
828                         if (servermode)
829                         {
830                                 if (!silent)
831                                 {
832                                         WriteChannelWithServ(ServerName,chan,user,"MODE %s %s",chan->name,outstr);
833                                         // M token for a usermode must go to all servers
834                                         char buffer[MAXBUF];
835                                         snprintf(buffer,MAXBUF,"M %s %s",chan->name, outstr);
836                                         NetSendToAll(buffer);
837                                 }
838                                         
839                         }
840                         else
841                         {
842                                 if (!silent)
843                                 {
844                                         WriteChannel(chan,user,"MODE %s %s",chan->name,outstr);
845                                         // M token for a usermode must go to all servers
846                                         char buffer[MAXBUF];
847                                         snprintf(buffer,MAXBUF,"m %s %s %s",user->nick,chan->name, outstr);
848                                         NetSendToAll(buffer);
849                                 }
850                         }
851                 }
852         }
853 }
854
855 // based on sourcemodes, return true or false to determine if umode is a valid mode a user may set on themselves or others.
856
857 bool allowed_umode(char umode, char* sourcemodes,bool adding)
858 {
859         log(DEBUG,"Allowed_umode: %c %s",umode,sourcemodes);
860         // RFC1459 specified modes
861         if ((umode == 'w') || (umode == 's') || (umode == 'i'))
862         {
863                 log(DEBUG,"umode %c allowed by RFC1459 scemantics",umode);
864                 return true;
865         }
866         
867         // user may not +o themselves or others, but an oper may de-oper other opers or themselves
868         if ((strchr(sourcemodes,'o')) && (!adding))
869         {
870                 log(DEBUG,"umode %c allowed by RFC1459 scemantics",umode);
871                 return true;
872         }
873         else if (umode == 'o')
874         {
875                 log(DEBUG,"umode %c allowed by RFC1459 scemantics",umode);
876                 return false;
877         }
878         
879         // process any module-defined modes that need oper
880         if ((ModeDefinedOper(umode,MT_CLIENT)) && (strchr(sourcemodes,'o')))
881         {
882                 log(DEBUG,"umode %c allowed by module handler (oper only mode)",umode);
883                 return true;
884         }
885         else
886         if (ModeDefined(umode,MT_CLIENT))
887         {
888                 // process any module-defined modes that don't need oper
889                 log(DEBUG,"umode %c allowed by module handler (non-oper mode)",umode);
890                 if ((ModeDefinedOper(umode,MT_CLIENT)) && (!strchr(sourcemodes,'o')))
891                 {
892                         // no, this mode needs oper, and this user 'aint got what it takes!
893                         return false;
894                 }
895                 return true;
896         }
897
898         // anything else - return false.
899         log(DEBUG,"umode %c not known by any ruleset",umode);
900         return false;
901 }
902
903 bool process_module_umode(char umode, userrec* source, void* dest, bool adding)
904 {
905         userrec* s2;
906         bool faked = false;
907         if (!source)
908         {
909                 s2 = new userrec;
910                 strncpy(s2->nick,ServerName,NICKMAX);
911                 strcpy(s2->modes,"o");
912                 s2->fd = -1;
913                 source = s2;
914                 faked = true;
915         }
916         string_list p;
917         p.clear();
918         if (ModeDefined(umode,MT_CLIENT))
919         {
920                 for (int i = 0; i <= MODCOUNT; i++)
921                 {
922                         if (modules[i]->OnExtendedMode(source,(void*)dest,umode,MT_CLIENT,adding,p))
923                         {
924                                 log(DEBUG,"Module claims umode %c",umode);
925                                 return true;
926                         }
927                 }
928                 log(DEBUG,"No module claims umode %c",umode);
929                 if (faked)
930                 {
931                         delete s2;
932                         source = NULL;
933                 }
934                 return false;
935         }
936         else
937         {
938                 if (faked)
939                 {
940                         delete s2;
941                         source = NULL;
942                 }
943                 return false;
944         }
945 }
946
947 void handle_mode(char **parameters, int pcnt, userrec *user)
948 {
949         chanrec* Ptr;
950         userrec* dest;
951         int can_change,i;
952         int direction = 1;
953         char outpars[MAXBUF];
954
955         dest = Find(parameters[0]);
956
957         if (!user)
958         {
959                 return;
960         }
961
962         if ((dest) && (pcnt == 1))
963         {
964                 WriteServ(user->fd,"221 %s :+%s",user->nick,user->modes);
965                 return;
966         }
967
968         if ((dest) && (pcnt > 1))
969         {
970                 char dmodes[MAXBUF];
971                 strncpy(dmodes,dest->modes,MAXBUF);
972                 log(DEBUG,"pulled up dest user modes: %s",dmodes);
973         
974                 can_change = 0;
975                 if (user != dest)
976                 {
977                         if (strchr(user->modes,'o'))
978                         {
979                                 can_change = 1;
980                         }
981                 }
982                 else
983                 {
984                         can_change = 1;
985                 }
986                 if (!can_change)
987                 {
988                         WriteServ(user->fd,"482 %s :Can't change mode for other users",user->nick);
989                         return;
990                 }
991                 
992                 strcpy(outpars,"+");
993                 direction = 1;
994
995                 if ((parameters[1][0] != '+') && (parameters[1][0] != '-'))
996                         return;
997
998                 for (int i = 0; i < strlen(parameters[1]); i++)
999                 {
1000                         if (parameters[1][i] == '+')
1001                         {
1002                                 if (direction != 1)
1003                                 {
1004                                         if ((outpars[strlen(outpars)-1] == '+') || (outpars[strlen(outpars)-1] == '-'))
1005                                         {
1006                                                 outpars[strlen(outpars)-1] = '+';
1007                                         }
1008                                         else
1009                                         {
1010                                                 strcat(outpars,"+");
1011                                         }
1012                                 }
1013                                 direction = 1;
1014                         }
1015                         else
1016                         if (parameters[1][i] == '-')
1017                         {
1018                                 if (direction != 0)
1019                                 {
1020                                         if ((outpars[strlen(outpars)-1] == '+') || (outpars[strlen(outpars)-1] == '-'))
1021                                         {
1022                                                 outpars[strlen(outpars)-1] = '-';
1023                                         }
1024                                         else
1025                                         {
1026                                                 strcat(outpars,"-");
1027                                         }
1028                                 }
1029                                 direction = 0;
1030                         }
1031                         else
1032                         {
1033                                 can_change = 0;
1034                                 if (strchr(user->modes,'o'))
1035                                 {
1036                                         can_change = 1;
1037                                 }
1038                                 else
1039                                 {
1040                                         if ((parameters[1][i] == 'i') || (parameters[1][i] == 'w') || (parameters[1][i] == 's') || (allowed_umode(parameters[1][i],user->modes,direction)))
1041                                         {
1042                                                 can_change = 1;
1043                                         }
1044                                 }
1045                                 if (can_change)
1046                                 {
1047                                         if (direction == 1)
1048                                         {
1049                                                 if ((!strchr(dmodes,parameters[1][i])) && (allowed_umode(parameters[1][i],user->modes,true)))
1050                                                 {
1051                                                         char umode = parameters[1][i];
1052                                                         if ((process_module_umode(umode, user, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
1053                                                         {
1054                                                                 dmodes[strlen(dmodes)+1]='\0';
1055                                                                 dmodes[strlen(dmodes)] = parameters[1][i];
1056                                                                 outpars[strlen(outpars)+1]='\0';
1057                                                                 outpars[strlen(outpars)] = parameters[1][i];
1058                                                         }
1059                                                 }
1060                                         }
1061                                         else
1062                                         {
1063                                                 if ((allowed_umode(parameters[1][i],user->modes,false)) && (strchr(dmodes,parameters[1][i])))
1064                                                 {
1065                                                         char umode = parameters[1][i];
1066                                                         if ((process_module_umode(umode, user, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
1067                                                         {
1068                                                                 int q = 0;
1069                                                                 char temp[MAXBUF];      
1070                                                                 char moo[MAXBUF];       
1071
1072                                                                 outpars[strlen(outpars)+1]='\0';
1073                                                                 outpars[strlen(outpars)] = parameters[1][i];
1074                                                         
1075                                                                 strcpy(temp,"");
1076                                                                 for (q = 0; q < strlen(dmodes); q++)
1077                                                                 {
1078                                                                         if (dmodes[q] != parameters[1][i])
1079                                                                         {
1080                                                                                 moo[0] = dmodes[q];
1081                                                                                 moo[1] = '\0';
1082                                                                                 strcat(temp,moo);
1083                                                                         }
1084                                                                 }
1085                                                                 strcpy(dmodes,temp);
1086                                                         }
1087                                                 }
1088                                         }
1089                                 }
1090                         }
1091                 }
1092                 if (strlen(outpars))
1093                 {
1094                         char b[MAXBUF];
1095                         strcpy(b,"");
1096                         int z = 0;
1097                         int i = 0;
1098                         while (i < strlen (outpars))
1099                         {
1100                                 b[z++] = outpars[i++];
1101                                 b[z] = '\0';
1102                                 if (i<strlen(outpars)-1)
1103                                 {
1104                                         if (((outpars[i] == '-') || (outpars[i] == '+')) && ((outpars[i+1] == '-') || (outpars[i+1] == '+')))
1105                                         {
1106                                                 // someones playing silly buggers and trying
1107                                                 // to put a +- or -+ into the line...
1108                                                 i++;
1109                                         }
1110                                 }
1111                                 if (i == strlen(outpars)-1)
1112                                 {
1113                                         if ((outpars[i] == '-') || (outpars[i] == '+'))
1114                                         {
1115                                                 i++;
1116                                         }
1117                                 }
1118                         }
1119
1120                         z = strlen(b)-1;
1121                         if ((b[z] == '-') || (b[z] == '+'))
1122                                 b[z] == '\0';
1123
1124                         if ((!strcmp(b,"+")) || (!strcmp(b,"-")))
1125                                 return;
1126
1127                         WriteTo(user, dest, "MODE %s :%s", dest->nick, b);
1128
1129                         // M token for a usermode must go to all servers
1130                         char buffer[MAXBUF];
1131                         snprintf(buffer,MAXBUF,"m %s %s %s",user->nick, dest->nick, b);
1132                         NetSendToAll(buffer);
1133
1134                         if (strlen(dmodes)>MAXMODES)
1135                         {
1136                                 dmodes[MAXMODES-1] = '\0';
1137                         }
1138                         log(DEBUG,"Stripped mode line");
1139                         log(DEBUG,"Line dest is now %s",dmodes);
1140                         strncpy(dest->modes,dmodes,MAXMODES);
1141
1142                 }
1143
1144                 return;
1145         }
1146         
1147         Ptr = FindChan(parameters[0]);
1148         if (Ptr)
1149         {
1150                 if (pcnt == 1)
1151                 {
1152                         /* just /modes #channel */
1153                         WriteServ(user->fd,"324 %s %s +%s",user->nick, Ptr->name, chanmodes(Ptr));
1154                         WriteServ(user->fd,"329 %s %s %d", user->nick, Ptr->name, Ptr->created);
1155                         return;
1156                 }
1157                 else
1158                 if (pcnt == 2)
1159                 {
1160                         if ((!strcmp(parameters[1],"+b")) || (!strcmp(parameters[1],"b")))
1161                         {
1162
1163                                 for (BanList::iterator i = Ptr->bans.begin(); i != Ptr->bans.end(); i++)
1164                                 {
1165                                         WriteServ(user->fd,"367 %s %s %s %s %d",user->nick, Ptr->name, i->data, i->set_by, i->set_time);
1166                                 }
1167                                 WriteServ(user->fd,"368 %s %s :End of channel ban list",user->nick, Ptr->name);
1168                                 return;
1169                         }
1170                 }
1171
1172                 if ((cstatus(user,Ptr) < STATUS_HOP) && (Ptr))
1173                 {
1174                         WriteServ(user->fd,"482 %s %s :You must be at least a half-operator to change modes on this channel",user->nick, Ptr->name);
1175                         return;
1176                 }
1177
1178                 process_modes(parameters,user,Ptr,cstatus(user,Ptr),pcnt,false,false,false);
1179         }
1180         else
1181         {
1182                 WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, parameters[0]);
1183         }
1184 }
1185
1186
1187
1188
1189 void server_mode(char **parameters, int pcnt, userrec *user)
1190 {
1191         chanrec* Ptr;
1192         userrec* dest;
1193         int can_change,i;
1194         int direction = 1;
1195         char outpars[MAXBUF];
1196
1197         dest = Find(parameters[0]);
1198         
1199         // fix: ChroNiCk found this - we cant use this as debug if its null!
1200         if (dest)
1201         {
1202                 log(DEBUG,"server_mode on %s",dest->nick);
1203         }
1204
1205         if ((dest) && (pcnt > 1))
1206         {
1207                 log(DEBUG,"params > 1");
1208
1209                 char dmodes[MAXBUF];
1210                 strncpy(dmodes,dest->modes,MAXBUF);
1211
1212                 strcpy(outpars,"+");
1213                 direction = 1;
1214
1215                 if ((parameters[1][0] != '+') && (parameters[1][0] != '-'))
1216                         return;
1217
1218                 for (int i = 0; i < strlen(parameters[1]); i++)
1219                 {
1220                         if (parameters[1][i] == '+')
1221                         {
1222                                 if (direction != 1)
1223                                 {
1224                                         if ((outpars[strlen(outpars)-1] == '+') || (outpars[strlen(outpars)-1] == '-'))
1225                                         {
1226                                                 outpars[strlen(outpars)-1] = '+';
1227                                         }
1228                                         else
1229                                         {
1230                                                 strcat(outpars,"+");
1231                                         }
1232                                 }
1233                                 direction = 1;
1234                         }
1235                         else
1236                         if (parameters[1][i] == '-')
1237                         {
1238                                 if (direction != 0)
1239                                 {
1240                                         if ((outpars[strlen(outpars)-1] == '+') || (outpars[strlen(outpars)-1] == '-'))
1241                                         {
1242                                                 outpars[strlen(outpars)-1] = '-';
1243                                         }
1244                                         else
1245                                         {
1246                                                 strcat(outpars,"-");
1247                                         }
1248                                 }
1249                                 direction = 0;
1250                         }
1251                         else
1252                         {
1253                                 log(DEBUG,"begin mode processing entry");
1254                                 can_change = 1;
1255                                 if (can_change)
1256                                 {
1257                                         if (direction == 1)
1258                                         {
1259                                                 log(DEBUG,"umode %c being added",parameters[1][i]);
1260                                                 if ((!strchr(dmodes,parameters[1][i])) && (allowed_umode(parameters[1][i],user->modes,true)))
1261                                                 {
1262                                                         char umode = parameters[1][i];
1263                                                         log(DEBUG,"umode %c is an allowed umode",umode);
1264                                                         if ((process_module_umode(umode, user, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
1265                                                         {
1266                                                                 dmodes[strlen(dmodes)+1]='\0';
1267                                                                 dmodes[strlen(dmodes)] = parameters[1][i];
1268                                                                 outpars[strlen(outpars)+1]='\0';
1269                                                                 outpars[strlen(outpars)] = parameters[1][i];
1270                                                         }
1271                                                 }
1272                                         }
1273                                         else
1274                                         {
1275                                                 // can only remove a mode they already have
1276                                                 log(DEBUG,"umode %c being removed",parameters[1][i]);
1277                                                 if ((allowed_umode(parameters[1][i],user->modes,false)) && (strchr(dmodes,parameters[1][i])))
1278                                                 {
1279                                                         char umode = parameters[1][i];
1280                                                         log(DEBUG,"umode %c is an allowed umode",umode);
1281                                                         if ((process_module_umode(umode, user, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
1282                                                         {
1283                                                                 int q = 0;
1284                                                                 char temp[MAXBUF];
1285                                                                 char moo[MAXBUF];       
1286
1287                                                                 outpars[strlen(outpars)+1]='\0';
1288                                                                 outpars[strlen(outpars)] = parameters[1][i];
1289                                                         
1290                                                                 strcpy(temp,"");
1291                                                                 for (q = 0; q < strlen(dmodes); q++)
1292                                                                 {
1293                                                                         if (dmodes[q] != parameters[1][i])
1294                                                                         {
1295                                                                                 moo[0] = dmodes[q];
1296                                                                                 moo[1] = '\0';
1297                                                                                 strcat(temp,moo);
1298                                                                         }
1299                                                                 }
1300                                                                 strcpy(dmodes,temp);
1301                                                         }
1302                                                 }
1303                                         }
1304                                 }
1305                         }
1306                 }
1307                 if (strlen(outpars))
1308                 {
1309                         char b[MAXBUF];
1310                         strcpy(b,"");
1311                         int z = 0;
1312                         int i = 0;
1313                         while (i < strlen (outpars))
1314                         {
1315                                 b[z++] = outpars[i++];
1316                                 b[z] = '\0';
1317                                 if (i<strlen(outpars)-1)
1318                                 {
1319                                         if (((outpars[i] == '-') || (outpars[i] == '+')) && ((outpars[i+1] == '-') || (outpars[i+1] == '+')))
1320                                         {
1321                                                 // someones playing silly buggers and trying
1322                                                 // to put a +- or -+ into the line...
1323                                                 i++;
1324                                         }
1325                                 }
1326                                 if (i == strlen(outpars)-1)
1327                                 {
1328                                         if ((outpars[i] == '-') || (outpars[i] == '+'))
1329                                         {
1330                                                 i++;
1331                                         }
1332                                 }
1333                         }
1334
1335                         z = strlen(b)-1;
1336                         if ((b[z] == '-') || (b[z] == '+'))
1337                                 b[z] == '\0';
1338
1339                         if ((!strcmp(b,"+")) || (!strcmp(b,"-")))
1340                                 return;
1341
1342                         WriteTo(user, dest, "MODE %s :%s", dest->nick, b);
1343
1344                         // M token for a usermode must go to all servers
1345                         char buffer[MAXBUF];
1346                         snprintf(buffer,MAXBUF,"m %s %s %s",user->nick, dest->nick, b);
1347                         NetSendToAll(buffer);
1348                         
1349                         if (strlen(dmodes)>MAXMODES)
1350                         {
1351                                 dmodes[MAXMODES-1] = '\0';
1352                         }
1353                         log(DEBUG,"Stripped mode line");
1354                         log(DEBUG,"Line dest is now %s",dmodes);
1355                         strncpy(dest->modes,dmodes,MAXMODES);
1356
1357                 }
1358
1359                 return;
1360         }
1361         
1362         Ptr = FindChan(parameters[0]);
1363         if (Ptr)
1364         {
1365                 process_modes(parameters,user,Ptr,STATUS_OP,pcnt,true,false,false);
1366         }
1367         else
1368         {
1369                 WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, parameters[0]);
1370         }
1371 }
1372
1373
1374
1375 void merge_mode(char **parameters, int pcnt)
1376 {
1377         chanrec* Ptr;
1378         userrec* dest;
1379         int can_change,i;
1380         int direction = 1;
1381         char outpars[MAXBUF];
1382
1383         dest = Find(parameters[0]);
1384         
1385         // fix: ChroNiCk found this - we cant use this as debug if its null!
1386         if (dest)
1387         {
1388                 log(DEBUG,"merge_mode on %s",dest->nick);
1389         }
1390
1391         if ((dest) && (pcnt > 1))
1392         {
1393                 log(DEBUG,"params > 1");
1394
1395                 char dmodes[MAXBUF];
1396                 strncpy(dmodes,dest->modes,MAXBUF);
1397
1398                 strcpy(outpars,"+");
1399                 direction = 1;
1400
1401                 if ((parameters[1][0] != '+') && (parameters[1][0] != '-'))
1402                         return;
1403
1404                 for (int i = 0; i < strlen(parameters[1]); i++)
1405                 {
1406                         if (parameters[1][i] == '+')
1407                         {
1408                                 if (direction != 1)
1409                                 {
1410                                         if ((outpars[strlen(outpars)-1] == '+') || (outpars[strlen(outpars)-1] == '-'))
1411                                         {
1412                                                 outpars[strlen(outpars)-1] = '+';
1413                                         }
1414                                         else
1415                                         {
1416                                                 strcat(outpars,"+");
1417                                         }
1418                                 }
1419                                 direction = 1;
1420                         }
1421                         else
1422                         if (parameters[1][i] == '-')
1423                         {
1424                                 if (direction != 0)
1425                                 {
1426                                         if ((outpars[strlen(outpars)-1] == '+') || (outpars[strlen(outpars)-1] == '-'))
1427                                         {
1428                                                 outpars[strlen(outpars)-1] = '-';
1429                                         }
1430                                         else
1431                                         {
1432                                                 strcat(outpars,"-");
1433                                         }
1434                                 }
1435                                 direction = 0;
1436                         }
1437                         else
1438                         {
1439                                 log(DEBUG,"begin mode processing entry");
1440                                 can_change = 1;
1441                                 if (can_change)
1442                                 {
1443                                         if (direction == 1)
1444                                         {
1445                                                 log(DEBUG,"umode %c being added",parameters[1][i]);
1446                                                 if ((!strchr(dmodes,parameters[1][i])) && (allowed_umode(parameters[1][i],"o",true)))
1447                                                 {
1448                                                         char umode = parameters[1][i];
1449                                                         log(DEBUG,"umode %c is an allowed umode",umode);
1450                                                         if ((process_module_umode(umode, NULL, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
1451                                                         {
1452                                                                 dmodes[strlen(dmodes)+1]='\0';
1453                                                                 dmodes[strlen(dmodes)] = parameters[1][i];
1454                                                                 outpars[strlen(outpars)+1]='\0';
1455                                                                 outpars[strlen(outpars)] = parameters[1][i];
1456                                                         }
1457                                                 }
1458                                         }
1459                                         else
1460                                         {
1461                                                 // can only remove a mode they already have
1462                                                 log(DEBUG,"umode %c being removed",parameters[1][i]);
1463                                                 if ((allowed_umode(parameters[1][i],"o",false)) && (strchr(dmodes,parameters[1][i])))
1464                                                 {
1465                                                         char umode = parameters[1][i];
1466                                                         log(DEBUG,"umode %c is an allowed umode",umode);
1467                                                         if ((process_module_umode(umode, NULL, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
1468                                                         {
1469                                                                 int q = 0;
1470                                                                 char temp[MAXBUF];
1471                                                                 char moo[MAXBUF];       
1472
1473                                                                 outpars[strlen(outpars)+1]='\0';
1474                                                                 outpars[strlen(outpars)] = parameters[1][i];
1475                                                         
1476                                                                 strcpy(temp,"");
1477                                                                 for (q = 0; q < strlen(dmodes); q++)
1478                                                                 {
1479                                                                         if (dmodes[q] != parameters[1][i])
1480                                                                         {
1481                                                                                 moo[0] = dmodes[q];
1482                                                                                 moo[1] = '\0';
1483                                                                                 strcat(temp,moo);
1484                                                                         }
1485                                                                 }
1486                                                                 strcpy(dmodes,temp);
1487                                                         }
1488                                                 }
1489                                         }
1490                                 }
1491                         }
1492                 }
1493                 if (strlen(outpars))
1494                 {
1495                         char b[MAXBUF];
1496                         strcpy(b,"");
1497                         int z = 0;
1498                         int i = 0;
1499                         while (i < strlen (outpars))
1500                         {
1501                                 b[z++] = outpars[i++];
1502                                 b[z] = '\0';
1503                                 if (i<strlen(outpars)-1)
1504                                 {
1505                                         if (((outpars[i] == '-') || (outpars[i] == '+')) && ((outpars[i+1] == '-') || (outpars[i+1] == '+')))
1506                                         {
1507                                                 // someones playing silly buggers and trying
1508                                                 // to put a +- or -+ into the line...
1509                                                 i++;
1510                                         }
1511                                 }
1512                                 if (i == strlen(outpars)-1)
1513                                 {
1514                                         if ((outpars[i] == '-') || (outpars[i] == '+'))
1515                                         {
1516                                                 i++;
1517                                         }
1518                                 }
1519                         }
1520
1521                         z = strlen(b)-1;
1522                         if ((b[z] == '-') || (b[z] == '+'))
1523                                 b[z] == '\0';
1524
1525                         if ((!strcmp(b,"+")) || (!strcmp(b,"-")))
1526                                 return;
1527
1528                         if (strlen(dmodes)>MAXMODES)
1529                         {
1530                                 dmodes[MAXMODES-1] = '\0';
1531                         }
1532                         log(DEBUG,"Stripped mode line");
1533                         log(DEBUG,"Line dest is now %s",dmodes);
1534                         strncpy(dest->modes,dmodes,MAXMODES);
1535
1536                 }
1537
1538                 return;
1539         }
1540         
1541         Ptr = FindChan(parameters[0]);
1542         if (Ptr)
1543         {
1544                 userrec s2;
1545                 strncpy(s2.nick,ServerName,NICKMAX);
1546                 strcpy(s2.modes,"o");
1547                 s2.fd = -1;
1548                 process_modes(parameters,&s2,Ptr,STATUS_OP,pcnt,true,true,false);
1549         }
1550 }
1551
1552
1553 void merge_mode2(char **parameters, int pcnt, userrec* user)
1554 {
1555         chanrec* Ptr;
1556         userrec* dest;
1557         int can_change,i;
1558         int direction = 1;
1559         char outpars[MAXBUF];
1560
1561         dest = Find(parameters[0]);
1562         
1563         // fix: ChroNiCk found this - we cant use this as debug if its null!
1564         if (dest)
1565         {
1566                 log(DEBUG,"merge_mode on %s",dest->nick);
1567         }
1568
1569         if ((dest) && (pcnt > 1))
1570         {
1571                 log(DEBUG,"params > 1");
1572
1573                 char dmodes[MAXBUF];
1574                 strncpy(dmodes,dest->modes,MAXBUF);
1575
1576                 strcpy(outpars,"+");
1577                 direction = 1;
1578
1579                 if ((parameters[1][0] != '+') && (parameters[1][0] != '-'))
1580                         return;
1581
1582                 for (int i = 0; i < strlen(parameters[1]); i++)
1583                 {
1584                         if (parameters[1][i] == '+')
1585                         {
1586                                 if (direction != 1)
1587                                 {
1588                                         if ((outpars[strlen(outpars)-1] == '+') || (outpars[strlen(outpars)-1] == '-'))
1589                                         {
1590                                                 outpars[strlen(outpars)-1] = '+';
1591                                         }
1592                                         else
1593                                         {
1594                                                 strcat(outpars,"+");
1595                                         }
1596                                 }
1597                                 direction = 1;
1598                         }
1599                         else
1600                         if (parameters[1][i] == '-')
1601                         {
1602                                 if (direction != 0)
1603                                 {
1604                                         if ((outpars[strlen(outpars)-1] == '+') || (outpars[strlen(outpars)-1] == '-'))
1605                                         {
1606                                                 outpars[strlen(outpars)-1] = '-';
1607                                         }
1608                                         else
1609                                         {
1610                                                 strcat(outpars,"-");
1611                                         }
1612                                 }
1613                                 direction = 0;
1614                         }
1615                         else
1616                         {
1617                                 log(DEBUG,"begin mode processing entry");
1618                                 can_change = 1;
1619                                 if (can_change)
1620                                 {
1621                                         if (direction == 1)
1622                                         {
1623                                                 log(DEBUG,"umode %c being added",parameters[1][i]);
1624                                                 if ((!strchr(dmodes,parameters[1][i])) && (allowed_umode(parameters[1][i],user->modes,true)))
1625                                                 {
1626                                                         char umode = parameters[1][i];
1627                                                         log(DEBUG,"umode %c is an allowed umode",umode);
1628                                                         if ((process_module_umode(umode, NULL, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
1629                                                         {
1630                                                                 dmodes[strlen(dmodes)+1]='\0';
1631                                                                 dmodes[strlen(dmodes)] = parameters[1][i];
1632                                                                 outpars[strlen(outpars)+1]='\0';
1633                                                                 outpars[strlen(outpars)] = parameters[1][i];
1634                                                         }
1635                                                 }
1636                                         }
1637                                         else
1638                                         {
1639                                                 // can only remove a mode they already have
1640                                                 log(DEBUG,"umode %c being removed",parameters[1][i]);
1641                                                 if ((allowed_umode(parameters[1][i],user->modes,false)) && (strchr(dmodes,parameters[1][i])))
1642                                                 {
1643                                                         char umode = parameters[1][i];
1644                                                         log(DEBUG,"umode %c is an allowed umode",umode);
1645                                                         if ((process_module_umode(umode, NULL, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
1646                                                         {
1647                                                                 int q = 0;
1648                                                                 char temp[MAXBUF];
1649                                                                 char moo[MAXBUF];       
1650
1651                                                                 outpars[strlen(outpars)+1]='\0';
1652                                                                 outpars[strlen(outpars)] = parameters[1][i];
1653                                                         
1654                                                                 strcpy(temp,"");
1655                                                                 for (q = 0; q < strlen(dmodes); q++)
1656                                                                 {
1657                                                                         if (dmodes[q] != parameters[1][i])
1658                                                                         {
1659                                                                                 moo[0] = dmodes[q];
1660                                                                                 moo[1] = '\0';
1661                                                                                 strcat(temp,moo);
1662                                                                         }
1663                                                                 }
1664                                                                 strcpy(dmodes,temp);
1665                                                         }
1666                                                 }
1667                                         }
1668                                 }
1669                         }
1670                 }
1671                 if (strlen(outpars))
1672                 {
1673                         char b[MAXBUF];
1674                         strcpy(b,"");
1675                         int z = 0;
1676                         int i = 0;
1677                         while (i < strlen (outpars))
1678                         {
1679                                 b[z++] = outpars[i++];
1680                                 b[z] = '\0';
1681                                 if (i<strlen(outpars)-1)
1682                                 {
1683                                         if (((outpars[i] == '-') || (outpars[i] == '+')) && ((outpars[i+1] == '-') || (outpars[i+1] == '+')))
1684                                         {
1685                                                 // someones playing silly buggers and trying
1686                                                 // to put a +- or -+ into the line...
1687                                                 i++;
1688                                         }
1689                                 }
1690                                 if (i == strlen(outpars)-1)
1691                                 {
1692                                         if ((outpars[i] == '-') || (outpars[i] == '+'))
1693                                         {
1694                                                 i++;
1695                                         }
1696                                 }
1697                         }
1698
1699                         z = strlen(b)-1;
1700                         if ((b[z] == '-') || (b[z] == '+'))
1701                                 b[z] == '\0';
1702
1703                         if ((!strcmp(b,"+")) || (!strcmp(b,"-")))
1704                                 return;
1705
1706                         WriteTo(user,dest,"MODE :%s",b);
1707
1708                         if (strlen(dmodes)>MAXMODES)
1709                         {
1710                                 dmodes[MAXMODES-1] = '\0';
1711                         }
1712                         log(DEBUG,"Stripped mode line");
1713                         log(DEBUG,"Line dest is now %s",dmodes);
1714                         strncpy(dest->modes,dmodes,MAXMODES);
1715
1716                 }
1717
1718                 return;
1719         }
1720         
1721         Ptr = FindChan(parameters[0]);
1722         if (Ptr)
1723         {
1724                 if ((cstatus(user,Ptr) < STATUS_HOP) && (Ptr))
1725                 {
1726                         return;
1727                 }
1728
1729                 process_modes(parameters,user,Ptr,cstatus(user,Ptr),pcnt,false,false,true);
1730         }
1731 }
1732
1733