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