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