]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/mode.cpp
Fixed weird bug where on mass join/part flood, the channel would be
[user/henk/code/inspircd.git] / src / mode.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  Inspire is copyright (C) 2002-2004 ChatSpike-Dev.
6  *                       E-mail:
7  *                <brain@chatspike.net>
8  *                <Craig@chatspike.net>
9  *     
10  * Written by Craig Edwards, Craig McLure, and others.
11  * This program is free but copyrighted software; see
12  *            the file COPYING for details.
13  *
14  * ---------------------------------------------------
15  */
16
17 #include "inspircd.h"
18 #include "inspircd_io.h"
19 #include "inspircd_util.h"
20 #include "inspircd_config.h"
21 #include <unistd.h>
22 #include <fcntl.h>
23 #include <sys/errno.h>
24 #include <sys/ioctl.h>
25 #include <sys/utsname.h>
26 #include <cstdio>
27 #include <time.h>
28 #include <string>
29 #ifdef GCC3
30 #include <ext/hash_map>
31 #else
32 #include <hash_map>
33 #endif
34 #include <map>
35 #include <sstream>
36 #include <vector>
37 #include <errno.h>
38 #include <deque>
39 #include <errno.h>
40 #include <unistd.h>
41 #include <sched.h>
42 #include "connection.h"
43 #include "users.h"
44 #include "servers.h"
45 #include "ctables.h"
46 #include "globals.h"
47 #include "modules.h"
48 #include "dynamic.h"
49 #include "wildcard.h"
50 #include "message.h"
51 #include "commands.h"
52 #include "xline.h"
53 #include "inspstring.h"
54
55 using namespace std;
56
57 extern int MODCOUNT;
58 extern std::vector<Module*> modules;
59 extern std::vector<ircd_module*> factory;
60 extern std::vector<std::string> module_names;
61
62
63 extern int LogLevel;
64 extern char ServerName[MAXBUF];
65 extern char Network[MAXBUF];
66 extern char ServerDesc[MAXBUF];
67 extern char AdminName[MAXBUF];
68 extern char AdminEmail[MAXBUF];
69 extern char AdminNick[MAXBUF];
70 extern char diepass[MAXBUF];
71 extern char restartpass[MAXBUF];
72 extern char motd[MAXBUF];
73 extern char rules[MAXBUF];
74 extern char list[MAXBUF];
75 extern char PrefixQuit[MAXBUF];
76 extern char DieValue[MAXBUF];
77
78 extern bool AllowHalfop;
79 extern bool AllowProtect;
80 extern bool AllowFounder;
81
82 extern time_t TIME;
83
84 char* give_ops(userrec *user,char *dest,chanrec *chan,int status)
85 {
86         userrec *d;
87         
88         if ((!user) || (!dest) || (!chan))
89         {
90                 log(DEFAULT,"*** BUG *** give_ops was given an invalid parameter");
91                 return NULL;
92         }
93
94         if (!isnick(dest))
95         {
96                 log(DEFAULT,"the target nickname given to give_ops was invalid");
97                 WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, dest);
98                 return NULL;
99         }
100         d = Find(dest);
101         if (!d)
102         {
103                 log(DEFAULT,"the target nickname given to give_ops couldnt be found");
104                 WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, dest);
105                 return NULL;
106         }
107         else
108         {
109
110                 int MOD_RESULT = 0;
111                 FOREACH_RESULT(OnAccessCheck(user,d,chan,AC_OP));
112                 
113                 if (MOD_RESULT == ACR_DENY)
114                         return NULL;
115                 if (MOD_RESULT == ACR_DEFAULT)
116                 {
117                         if ((status < STATUS_OP) && (!is_uline(user->server)))
118                         {
119                                 log(DEBUG,"%s cant give ops to %s because they nave status %d and needs %d",user->nick,dest,status,STATUS_OP);
120                                 WriteServ(user->fd,"482 %s %s :You're not a channel operator",user->nick, chan->name);
121                                 return NULL;
122                         }
123                 }
124
125
126                 for (int i = 0; i != MAXCHANS; i++)
127                 {
128                         if ((d->chans[i].channel != NULL) && (chan != NULL))
129                         if (!strcasecmp(d->chans[i].channel->name,chan->name))
130                         {
131                         if (d->chans[i].uc_modes & UCMODE_OP)
132                                 {
133                                         /* mode already set on user, dont allow multiple */
134                                         log(DEFAULT,"The target user given to give_ops was already opped on the channel");
135                                         return NULL;
136                                 }
137                                 d->chans[i].uc_modes = d->chans[i].uc_modes | UCMODE_OP;
138                                 log(DEBUG,"gave ops: %s %s",d->chans[i].channel->name,d->nick);
139                                 return d->nick;
140                         }
141                 }
142                 log(DEFAULT,"The target channel given to give_ops was not in the users mode list");
143         }
144         return NULL;
145 }
146
147 char* give_hops(userrec *user,char *dest,chanrec *chan,int status)
148 {
149         userrec *d;
150         
151         if ((!user) || (!dest) || (!chan))
152         {
153                 log(DEFAULT,"*** BUG *** give_hops was given an invalid parameter");
154                 return NULL;
155         }
156
157         d = Find(dest);
158         if (!isnick(dest))
159         {
160                 WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, dest);
161                 return NULL;
162         }
163         if (!d)
164         {
165                 WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, dest);
166                 return NULL;
167         }
168         else
169         {
170                 int MOD_RESULT = 0;
171                 FOREACH_RESULT(OnAccessCheck(user,d,chan,AC_HALFOP));
172                 
173                 if (MOD_RESULT == ACR_DENY)
174                         return NULL;
175                 if (MOD_RESULT == ACR_DEFAULT)
176                 {
177                         if ((status < STATUS_OP) && (!is_uline(user->server)))
178                         {
179                                 WriteServ(user->fd,"482 %s %s :You're not a channel operator",user->nick, chan->name);
180                                 return NULL;
181                         }
182                 }
183
184                 for (int i = 0; i != MAXCHANS; i++)
185                 {
186                         if ((d->chans[i].channel != NULL) && (chan != NULL))
187                         if (!strcasecmp(d->chans[i].channel->name,chan->name))
188                         {
189                                 if (d->chans[i].uc_modes & UCMODE_HOP)
190                                 {
191                                         /* mode already set on user, dont allow multiple */
192                                         return NULL;
193                                 }
194                                 d->chans[i].uc_modes = d->chans[i].uc_modes | UCMODE_HOP;
195                                 log(DEBUG,"gave h-ops: %s %s",d->chans[i].channel->name,d->nick);
196                                 return d->nick;
197                         }
198                 }
199         }
200         return NULL;
201 }
202
203 char* give_voice(userrec *user,char *dest,chanrec *chan,int status)
204 {
205         userrec *d;
206         
207         if ((!user) || (!dest) || (!chan))
208         {
209                 log(DEFAULT,"*** BUG *** give_voice was given an invalid parameter");
210                 return NULL;
211         }
212
213         d = Find(dest);
214         if (!isnick(dest))
215         {
216                 WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, dest);
217                 return NULL;
218         }
219         if (!d)
220         {
221                 WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, dest);
222                 return NULL;
223         }
224         else
225         {
226                 int MOD_RESULT = 0;
227                 FOREACH_RESULT(OnAccessCheck(user,d,chan,AC_VOICE));
228                 
229                 if (MOD_RESULT == ACR_DENY)
230                         return NULL;
231                 if (MOD_RESULT == ACR_DEFAULT)
232                 {
233                         if ((status < STATUS_HOP) && (!is_uline(user->server)))
234                         {
235                                 WriteServ(user->fd,"482 %s %s :You must be at least a half-operator to change modes on this channel",user->nick, chan->name);
236                                 return NULL;
237                         }
238                 }
239
240                 for (int i = 0; i != MAXCHANS; i++)
241                 {
242                         if ((d->chans[i].channel != NULL) && (chan != NULL))
243                         if (!strcasecmp(d->chans[i].channel->name,chan->name))
244                         {
245                                 if (d->chans[i].uc_modes & UCMODE_VOICE)
246                                 {
247                                         /* mode already set on user, dont allow multiple */
248                                         return NULL;
249                                 }
250                                 d->chans[i].uc_modes = d->chans[i].uc_modes | UCMODE_VOICE;
251                                 log(DEBUG,"gave voice: %s %s",d->chans[i].channel->name,d->nick);
252                                 return d->nick;
253                         }
254                 }
255         }
256         return NULL;
257 }
258
259 char* take_ops(userrec *user,char *dest,chanrec *chan,int status)
260 {
261         userrec *d;
262         
263         if ((!user) || (!dest) || (!chan))
264         {
265                 log(DEFAULT,"*** BUG *** take_ops was given an invalid parameter");
266                 return NULL;
267         }
268
269         d = Find(dest);
270         if (!isnick(dest))
271         {
272                 log(DEBUG,"take_ops was given an invalid target nickname of %s",dest);
273                 WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, dest);
274                 return NULL;
275         }
276         if (!d)
277         {
278                 log(DEBUG,"take_ops couldnt resolve the target nickname: %s",dest);
279                 WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, dest);
280                 return NULL;
281         }
282         else
283         {
284                 int MOD_RESULT = 0;
285                 FOREACH_RESULT(OnAccessCheck(user,d,chan,AC_DEOP));
286                 
287                 if (MOD_RESULT == ACR_DENY)
288                         return NULL;
289                 if (MOD_RESULT == ACR_DEFAULT)
290                 {
291                         if ((status < STATUS_OP) && (!is_uline(user->server)))
292                         {
293                                 WriteServ(user->fd,"482 %s %s :You are not a channel operator",user->nick, chan->name);
294                                 return NULL;
295                         }
296                 }
297
298                 for (int i = 0; i != MAXCHANS; i++)
299                 {
300                         if ((d->chans[i].channel != NULL) && (chan != NULL))
301                         if (!strcasecmp(d->chans[i].channel->name,chan->name))
302                         {
303                                 if ((d->chans[i].uc_modes & UCMODE_OP) == 0)
304                                 {
305                                         /* mode already set on user, dont allow multiple */
306                                         return NULL;
307                                 }
308                                 d->chans[i].uc_modes ^= UCMODE_OP;
309                                 log(DEBUG,"took ops: %s %s",d->chans[i].channel->name,d->nick);
310                                 return d->nick;
311                         }
312                 }
313                 log(DEBUG,"take_ops couldnt locate the target channel in the target users list");
314         }
315         return NULL;
316 }
317
318 char* take_hops(userrec *user,char *dest,chanrec *chan,int status)
319 {
320         userrec *d;
321         
322         if ((!user) || (!dest) || (!chan))
323         {
324                 log(DEFAULT,"*** BUG *** take_hops was given an invalid parameter");
325                 return NULL;
326         }
327
328         d = Find(dest);
329         if (!isnick(dest))
330         {
331                 WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, dest);
332                 return NULL;
333         }
334         if (!d)
335         {
336                 WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, dest);
337                 return NULL;
338         }
339         else
340         {
341                 int MOD_RESULT = 0;
342                 FOREACH_RESULT(OnAccessCheck(user,d,chan,AC_DEHALFOP));
343                 
344                 if (MOD_RESULT == ACR_DENY)
345                         return NULL;
346                 if (MOD_RESULT == ACR_DEFAULT)
347                 {
348                         if ((status < STATUS_OP) && (!is_uline(user->server)))
349                         {
350                                 WriteServ(user->fd,"482 %s %s :You are not a channel operator",user->nick, chan->name);
351                                 return NULL;
352                         }
353                 }
354
355                 for (int i = 0; i != MAXCHANS; i++)
356                 {
357                         if ((d->chans[i].channel != NULL) && (chan != NULL))
358                         if (!strcasecmp(d->chans[i].channel->name,chan->name))
359                         {
360                                 if ((d->chans[i].uc_modes & UCMODE_HOP) == 0)
361                                 {
362                                         /* mode already set on user, dont allow multiple */
363                                         return NULL;
364                                 }
365                                 d->chans[i].uc_modes ^= UCMODE_HOP;
366                                 log(DEBUG,"took h-ops: %s %s",d->chans[i].channel->name,d->nick);
367                                 return d->nick;
368                         }
369                 }
370         }
371         return NULL;
372 }
373
374 char* take_voice(userrec *user,char *dest,chanrec *chan,int status)
375 {
376         userrec *d;
377         
378         if ((!user) || (!dest) || (!chan))
379         {
380                 log(DEFAULT,"*** BUG *** take_voice was given an invalid parameter");
381                 return NULL;
382         }
383
384         d = Find(dest);
385         if (!isnick(dest))
386         {
387                 WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, dest);
388                 return NULL;
389         }
390         if (!d)
391         {
392                 WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, dest);
393                 return NULL;
394         }
395         else
396         {
397                 int MOD_RESULT = 0;
398                 FOREACH_RESULT(OnAccessCheck(user,d,chan,AC_DEVOICE));
399                 
400                 if (MOD_RESULT == ACR_DENY)
401                         return NULL;
402                 if (MOD_RESULT == ACR_DEFAULT)
403                 {
404                         if ((status < STATUS_HOP) && (!is_uline(user->server)))
405                         {
406                                 WriteServ(user->fd,"482 %s %s :You must be at least a half-operator to change modes on this channel",user->nick, chan->name);
407                                 return NULL;
408                         }
409                 }
410
411                 for (int i = 0; i != MAXCHANS; i++)
412                 {
413                         if ((d->chans[i].channel != NULL) && (chan != NULL))
414                         if (!strcasecmp(d->chans[i].channel->name,chan->name))
415                         {
416                                 if ((d->chans[i].uc_modes & UCMODE_VOICE) == 0)
417                                 {
418                                         /* mode already set on user, dont allow multiple */
419                                         return NULL;
420                                 }
421                                 d->chans[i].uc_modes ^= UCMODE_VOICE;
422                                 log(DEBUG,"took voice: %s %s",d->chans[i].channel->name,d->nick);
423                                 return d->nick;
424                         }
425                 }
426         }
427         return NULL;
428 }
429
430 char* add_ban(userrec *user,char *dest,chanrec *chan,int status)
431 {
432         if ((!user) || (!dest) || (!chan)) {
433                 log(DEFAULT,"*** BUG *** add_ban was given an invalid parameter");
434                 return NULL;
435         }
436
437         BanItem b;
438         if ((!user) || (!dest) || (!chan))
439                 return NULL;
440         int l = strlen(dest);
441         if (strchr(dest,'!')==0)
442                 return NULL;
443         if (strchr(dest,'@')==0)
444                 return NULL;
445         for (int i = 0; i < l; i++)
446                 if (dest[i] < 32)
447                         return NULL;
448         for (int i = 0; i < l; i++)
449                 if (dest[i] > 126)
450                         return NULL;
451         int c = 0;
452         for (int i = 0; i < l; i++)
453                 if (dest[i] == '!')
454                         c++;
455         if (c>1)
456                 return NULL;
457         c = 0;
458         for (int i = 0; i < l; i++)
459                 if (dest[i] == '@')
460                         c++;
461         if (c>1)
462                 return NULL;
463
464         long maxbans = GetMaxBans(chan->name);
465         if (chan->bans.size() > maxbans)
466         {
467                 WriteServ(user->fd,"478 %s %s :Channel ban list for %s is full (maximum entries for this channel is %d)",user->nick, chan->name,chan->name,maxbans);
468                 return NULL;
469         }
470
471         log(DEBUG,"add_ban: %s %s",chan->name,user->nick);
472
473         int MOD_RESULT = 0;
474         FOREACH_RESULT(OnAddBan(user,chan,dest));
475         if (MOD_RESULT)
476                 return NULL;
477
478         TidyBan(dest);
479         for (BanList::iterator i = chan->bans.begin(); i != chan->bans.end(); i++)
480         {
481                 if (!strcasecmp(i->data,dest))
482                 {
483                         // dont allow a user to set the same ban twice
484                         return NULL;
485                 }
486         }
487
488         b.set_time = TIME;
489         strncpy(b.data,dest,MAXBUF);
490         strncpy(b.set_by,user->nick,NICKMAX);
491         chan->bans.push_back(b);
492         return dest;
493 }
494
495 char* take_ban(userrec *user,char *dest,chanrec *chan,int status)
496 {
497         if ((!user) || (!dest) || (!chan)) {
498                 log(DEFAULT,"*** BUG *** take_ban was given an invalid parameter");
499                 return 0;
500         }
501
502         log(DEBUG,"del_ban: %s %s",chan->name,user->nick);
503         for (BanList::iterator i = chan->bans.begin(); i != chan->bans.end(); i++)
504         {
505                 if (!strcasecmp(i->data,dest))
506                 {
507                         int MOD_RESULT = 0;
508                         FOREACH_RESULT(OnDelBan(user,chan,dest));
509                         if (MOD_RESULT)
510                                 return NULL;
511                         chan->bans.erase(i);
512                         return dest;
513                 }
514         }
515         return NULL;
516 }
517
518 // tidies up redundant modes, e.g. +nt-nt+i becomes +-+i,
519 // a section further down the chain tidies up the +-+- crap.
520 std::string compress_modes(std::string modes,bool channelmodes)
521 {
522         int counts[127];
523         bool active[127];
524         int delta = 1;
525         memset(counts,0,sizeof(counts));
526         memset(active,0,sizeof(active));
527         log(DEBUG,"compress_modes: %s",modes.c_str());
528         for (int i = 0; i < modes.length(); i++)
529         {
530                 if ((modes[i] == '+') || (modes[i] == '-'))
531                         continue;
532                 if (channelmodes)
533                 {
534                         if ((strchr("itnmsp",modes[i])) || ((ModeDefined(modes[i],MT_CHANNEL)) && (ModeDefinedOn(modes[i],MT_CHANNEL)==0) && (ModeDefinedOff(modes[i],MT_CHANNEL)==0)))
535                         {
536                                 log(DEBUG,"Tidy mode %c",modes[i]);
537                                 counts[(unsigned int)modes[i]]++;
538                                 active[(unsigned int)modes[i]] = true;
539                         }
540                 }
541                 else
542                 {
543                         log(DEBUG,"Tidy mode %c",modes[i]);
544                         counts[(unsigned int)modes[i]]++;
545                         active[(unsigned int)modes[i]] = true;
546                 }
547         }
548         for (int j = 65; j < 127; j++)
549         {
550                 if ((counts[j] > 1) && (active[j] == true))
551                 {
552                         static char v[2];
553                         v[0] = (unsigned char)j;
554                         v[1] = '\0';
555                         std::string mode_str = v;
556                         std::string::size_type pos = modes.find(mode_str);
557                         if (pos != std::string::npos)
558                         {
559                                 log(DEBUG,"all occurances of mode %c to be deleted...",(unsigned char)j);
560                                 while (modes.find(mode_str) != std::string::npos)
561                                         modes.erase(modes.find(mode_str),1);
562                                 log(DEBUG,"New mode line: %s",modes.c_str());
563                         }
564                 }
565         }
566         return modes;
567 }
568
569 void process_modes(char **parameters,userrec* user,chanrec *chan,int status, int pcnt, bool servermode, bool silent, bool local)
570 {
571         if (!parameters) {
572                 log(DEFAULT,"*** BUG *** process_modes was given an invalid parameter");
573                 return;
574         }
575
576         char modelist[MAXBUF];
577         char outlist[MAXBUF];
578         char outstr[MAXBUF];
579         char outpars[32][MAXBUF];
580         int param = 2;
581         int pc = 0;
582         int ptr = 0;
583         int mdir = 1;
584         char* r = NULL;
585         bool k_set = false, l_set = false, previously_set_l = false, previously_unset_l = false, previously_set_k = false, previously_unset_k = false;
586
587         if (pcnt < 2)
588         {
589                 return;
590         }
591
592         int MOD_RESULT = 0;
593         FOREACH_RESULT(OnAccessCheck(user,NULL,chan,AC_GENERAL_MODE));
594         
595         if (MOD_RESULT == ACR_DENY)
596                 return;
597
598         log(DEBUG,"process_modes: start: parameters=%d",pcnt);
599
600         strlcpy(modelist,parameters[1],MAXBUF); /* mode list, e.g. +oo-o *
601                                                  * parameters[2] onwards are parameters for
602                                                  * modes that require them :) */
603         strlcpy(outlist,"+",MAXBUF);
604         mdir = 1;
605
606         log(DEBUG,"process_modes: modelist: %s",modelist);
607
608         std::string tidied = compress_modes(modelist,true);
609         strlcpy(modelist,tidied.c_str(),MAXBUF);
610
611         int len = strlen(modelist);
612         while (modelist[len-1] == ' ')
613                 modelist[--len] = '\0';
614         for (ptr = 0; ptr < len; ptr++)
615         {
616                 r = NULL;
617
618                 {
619                         log(DEBUG,"process_modes: modechar: %c",modelist[ptr]);
620
621                         char modechar = modelist[ptr];
622                         switch (modelist[ptr])
623                         {
624                                 case '-':
625                                         if (mdir != 0)
626                                         {
627                                                 int t = strlen(outlist)-1;
628                                                 if ((outlist[t] == '+') || (outlist[t] == '-'))
629                                                 {
630                                                         outlist[t] = '-';
631                                                 }
632                                                 else
633                                                 {
634                                                         strcat(outlist,"-");
635                                                 }
636                                         }
637                                         mdir = 0;
638                                         
639                                 break;                  
640
641                                 case '+':
642                                         if (mdir != 1)
643                                         {
644                                                 int t = strlen(outlist)-1;
645                                                 if ((outlist[t] == '+') || (outlist[t] == '-'))
646                                                 {
647                                                         outlist[t] = '+';
648                                                 }
649                                                 else
650                                                 {
651                                                         strcat(outlist,"+");
652                                                 }
653                                         }
654                                         mdir = 1;
655                                 break;
656
657                                 case 'o':
658                                         log(DEBUG,"Ops");
659                                         if ((param >= pcnt)) break;
660                                         log(DEBUG,"Enough parameters left");
661                                         if (mdir == 1)
662                                         {
663                                                 MOD_RESULT = 0;
664                                                 FOREACH_RESULT(OnRawMode(user, chan, 'o', parameters[param], true, 1));
665                                                 if (!MOD_RESULT)
666                                                 {
667                                                         log(DEBUG,"calling give_ops");
668                                                         r = give_ops(user,parameters[param++],chan,status);
669                                                 }
670                                                 else param++;
671                                         }
672                                         else
673                                         {
674                                                 MOD_RESULT = 0;
675                                                 FOREACH_RESULT(OnRawMode(user, chan, 'o', parameters[param], false, 1));
676                                                 if (!MOD_RESULT)
677                                                 {
678                                                         log(DEBUG,"calling take_ops");
679                                                         r = take_ops(user,parameters[param++],chan,status);
680                                                 }
681                                                 else param++;
682                                         }
683                                         if (r)
684                                         {
685                                                 strlcat(outlist,"o",MAXBUF);
686                                                 strlcpy(outpars[pc++],r,MAXBUF);
687                                         }
688                                 break;
689                         
690                                 case 'h':
691                                         if (((param >= pcnt)) || (!AllowHalfop)) break;
692                                         if (mdir == 1)
693                                         {
694                                                 MOD_RESULT = 0;
695                                                 FOREACH_RESULT(OnRawMode(user, chan, 'h', parameters[param], true, 1));
696                                                 if (!MOD_RESULT)
697                                                 {
698                                                         r = give_hops(user,parameters[param++],chan,status);
699                                                 }
700                                                 else param++;
701                                         }
702                                         else
703                                         {
704                                                 MOD_RESULT = 0;
705                                                 FOREACH_RESULT(OnRawMode(user, chan, 'h', parameters[param], false, 1));
706                                                 if (!MOD_RESULT)
707                                                 {
708                                                         r = take_hops(user,parameters[param++],chan,status);
709                                                 }
710                                                 else param++;
711                                         }
712                                         if (r)
713                                         {
714                                                 strlcat(outlist,"h",MAXBUF);
715                                                 strlcpy(outpars[pc++],r,MAXBUF);
716                                         }
717                                 break;
718                         
719                                 
720                                 case 'v':
721                                         if ((param >= pcnt)) break;
722                                         if (mdir == 1)
723                                         {
724                                                 MOD_RESULT = 0;
725                                                 FOREACH_RESULT(OnRawMode(user, chan, 'v', parameters[param], true, 1));
726                                                 if (!MOD_RESULT)
727                                                 {
728                                                         r = give_voice(user,parameters[param++],chan,status);
729                                                 }
730                                                 else param++;
731                                         }
732                                         else
733                                         {
734                                                 MOD_RESULT = 0;
735                                                 FOREACH_RESULT(OnRawMode(user, chan, 'v', parameters[param], false, 1));
736                                                 if (!MOD_RESULT)
737                                                 {
738                                                         r = take_voice(user,parameters[param++],chan,status);
739                                                 }
740                                                 else param++;
741                                         }
742                                         if (r)
743                                         {
744                                                 strlcat(outlist,"v",MAXBUF);
745                                                 strlcpy(outpars[pc++],r,MAXBUF);
746                                         }
747                                 break;
748                                 
749                                 case 'b':
750                                         if ((param >= pcnt)) break;
751                                         if (mdir == 1)
752                                         {
753                                                 MOD_RESULT = 0;
754                                                 FOREACH_RESULT(OnRawMode(user, chan, 'b', parameters[param], true, 1));
755                                                 if (!MOD_RESULT)
756                                                 {
757                                                         r = add_ban(user,parameters[param++],chan,status);
758                                                 }
759                                                 else param++;
760                                         }
761                                         else
762                                         {
763                                                 MOD_RESULT = 0;
764                                                 FOREACH_RESULT(OnRawMode(user, chan, 'b', parameters[param], false, 1));
765                                                 if (!MOD_RESULT)
766                                                 {
767                                                         r = take_ban(user,parameters[param++],chan,status);
768                                                 }
769                                                 else param++;
770                                         }
771                                         if (r)
772                                         {
773                                                 strlcat(outlist,"b",MAXBUF);
774                                                 strlcpy(outpars[pc++],parameters[param-1],MAXBUF);
775                                         }
776                                 break;
777
778
779                                 case 'k':
780                                         if ((param >= pcnt))
781                                                 break;
782
783                                         if (mdir == 1)
784                                         {
785                                                 if (k_set)
786                                                         break;
787
788                                                 if (previously_unset_k)
789                                                         break;
790                                                 previously_set_k = true;
791                                                 
792                                                 if (!strcmp(chan->key,""))
793                                                 {
794                                                         MOD_RESULT = 0;
795                                                         FOREACH_RESULT(OnRawMode(user, chan, 'k', parameters[param], true, 1));
796                                                         if (!MOD_RESULT)
797                                                         {
798                                                                 strcat(outlist,"k");
799                                                                 char key[MAXBUF];
800                                                                 strlcpy(key,parameters[param++],32);
801                                                                 strlcpy(outpars[pc++],key,MAXBUF);
802                                                                 strlcpy(chan->key,key,MAXBUF);
803                                                                 k_set = true;
804                                                         }
805                                                         else param++;
806                                                 }
807                                         }
808                                         else
809                                         {
810                                                 /* checks on -k are case sensitive and only accurate to the
811                                                    first 32 characters */
812                                                 if (previously_set_k)
813                                                         break;
814                                                 previously_unset_k = true;
815
816                                                 char key[MAXBUF];
817                                                 MOD_RESULT = 0;
818                                                 FOREACH_RESULT(OnRawMode(user, chan, 'k', parameters[param], false, 1));
819                                                 if (!MOD_RESULT)
820                                                 {
821                                                         strlcpy(key,parameters[param++],32);
822                                                         /* only allow -k if correct key given */
823                                                         if (!strcmp(chan->key,key))
824                                                         {
825                                                                 strlcat(outlist,"k",MAXBUF);
826                                                                 strlcpy(chan->key,"",MAXBUF);
827                                                                 strlcpy(outpars[pc++],key,MAXBUF);
828                                                         }
829                                                 }
830                                                 else param++;
831                                         }
832                                 break;
833                                 
834                                 case 'l':
835                                         if (mdir == 0)
836                                         {
837                                                 if (previously_set_l)
838                                                         break;
839                                                 previously_unset_l = true;
840                                                 MOD_RESULT = 0;
841                                                 FOREACH_RESULT(OnRawMode(user, chan, 'l', "", false, 0));
842                                                 if (!MOD_RESULT)
843                                                 {
844                                                         if (chan->limit)
845                                                         {
846                                                                 strcat(outlist,"l");
847                                                                 chan->limit = 0;
848                                                         }
849                                                 }
850                                         }
851                                         
852                                         if ((param >= pcnt)) break;
853                                         if (mdir == 1)
854                                         {
855                                                 if (l_set)
856                                                         break;
857                                                 if (previously_unset_l)
858                                                         break;
859                                                 previously_set_l = true;
860                                                 bool invalid = false;
861                                                 for (int i = 0; i < strlen(parameters[param]); i++)
862                                                 {
863                                                         if ((parameters[param][i] < '0') || (parameters[param][i] > '9'))
864                                                         {
865                                                                 invalid = true;
866                                                         }
867                                                 }
868                                                 if (atoi(parameters[param]) < 1)
869                                                 {
870                                                         invalid = true;
871                                                 }
872
873                                                 if (invalid)
874                                                         break;
875
876                                                 MOD_RESULT = 0;
877                                                 FOREACH_RESULT(OnRawMode(user, chan, 'l', parameters[param], true, 1));
878                                                 if (!MOD_RESULT)
879                                                 {
880         
881                                                         chan->limit = atoi(parameters[param]);
882                                                         
883                                                         // reported by mech: large values cause underflow
884                                                         if (chan->limit < 0)
885                                                                 chan->limit = 0x7FFFFF;
886                                                 }
887                                                         
888                                                 if (chan->limit)
889                                                 {
890                                                         strlcat(outlist,"l",MAXBUF);
891                                                         strlcpy(outpars[pc++],parameters[param++],MAXBUF);
892                                                         l_set = true;
893                                                 }
894                                         }
895                                 break;
896                                 
897                                 case 'i':
898                                         MOD_RESULT = 0;
899                                         FOREACH_RESULT(OnRawMode(user, chan, 'i', "", mdir, 0));
900                                         if (!MOD_RESULT)
901                                         {
902                                                 if (chan->inviteonly != mdir)
903                                                 {
904                                                         strlcat(outlist,"i",MAXBUF);
905                                                 }
906                                                 chan->inviteonly = mdir;
907                                         }
908                                 break;
909                                 
910                                 case 't':
911                                         MOD_RESULT = 0;
912                                         FOREACH_RESULT(OnRawMode(user, chan, 't', "", mdir, 0));
913                                         if (!MOD_RESULT)
914                                         {
915                                                 if (chan->topiclock != mdir)
916                                                 {
917                                                         strlcat(outlist,"t",MAXBUF);
918                                                 }
919                                                 chan->topiclock = mdir;
920                                         }
921                                 break;
922                                 
923                                 case 'n':
924                                         MOD_RESULT = 0;
925                                         FOREACH_RESULT(OnRawMode(user, chan, 'n', "", mdir, 0));
926                                         if (!MOD_RESULT)
927                                         {
928                                                 if (chan->noexternal != mdir)
929                                                 {
930                                                         strlcat(outlist,"n",MAXBUF);
931                                                 }
932                                                 chan->noexternal = mdir;
933                                         }
934                                 break;
935                                 
936                                 case 'm':
937                                         MOD_RESULT = 0;
938                                         FOREACH_RESULT(OnRawMode(user, chan, 'm', "", mdir, 0));
939                                         if (!MOD_RESULT)
940                                         {
941                                                 if (chan->moderated != mdir)
942                                                 {
943                                                         strlcat(outlist,"m",MAXBUF);
944                                                 }
945                                                 chan->moderated = mdir;
946                                         }
947                                 break;
948                                 
949                                 case 's':
950                                         MOD_RESULT = 0;
951                                         FOREACH_RESULT(OnRawMode(user, chan, 's', "", mdir, 0));
952                                         if (!MOD_RESULT)
953                                         {
954                                                 if (chan->secret != mdir)
955                                                 {
956                                                         strcat(outlist,"s");
957                                                         if (chan->c_private)
958                                                         {
959                                                                 chan->c_private = 0;
960                                                                 if (mdir)
961                                                                 {
962                                                                         strlcat(outlist,"-p+",MAXBUF);
963                                                                 }
964                                                                 else
965                                                                 {
966                                                                         strlcat(outlist,"+p-",MAXBUF);
967                                                                 }
968                                                         }
969                                                 }
970                                                 chan->secret = mdir;
971                                         }
972                                 break;
973                                 
974                                 case 'p':
975                                         MOD_RESULT = 0;
976                                         FOREACH_RESULT(OnRawMode(user, chan, 'p', "", mdir, 0));
977                                         if (!MOD_RESULT)
978                                         {
979                                                 if (chan->c_private != mdir)
980                                                 {
981                                                         strlcat(outlist,"p",MAXBUF);
982                                                         if (chan->secret)
983                                                         {
984                                                                 chan->secret = 0;
985                                                                 if (mdir)
986                                                                 {
987                                                                         strlcat(outlist,"-s+",MAXBUF);
988                                                                 }
989                                                                 else
990                                                                 {
991                                                                         strlcat(outlist,"+s-",MAXBUF);
992                                                                 }
993                                                         }
994                                                 }
995                                                 chan->c_private = mdir;
996                                         }
997                                 break;
998                                 
999                                 default:
1000                                         log(DEBUG,"Preprocessing custom mode %c: modelist: %s",modechar,chan->custom_modes);
1001                                         string_list p;
1002                                         p.clear();
1003                                         if (((!strchr(chan->custom_modes,modechar)) && (!mdir)) || ((strchr(chan->custom_modes,modechar)) && (mdir)))
1004                                         {
1005                                                 if (!ModeIsListMode(modechar,MT_CHANNEL))
1006                                                 {
1007                                                         log(DEBUG,"Mode %c isnt set on %s but trying to remove!",modechar,chan->name);
1008                                                         break;
1009                                                 }
1010                                         }
1011                                         if (ModeDefined(modechar,MT_CHANNEL))
1012                                         {
1013                                                 log(DEBUG,"A module has claimed this mode");
1014                                                 if (param<pcnt)
1015                                                 {
1016                                                         if ((ModeDefinedOn(modechar,MT_CHANNEL)>0) && (mdir))
1017                                                         {
1018                                                                 p.push_back(parameters[param]);
1019                                                         }
1020                                                         if ((ModeDefinedOff(modechar,MT_CHANNEL)>0) && (!mdir))
1021                                                         {
1022                                                                 p.push_back(parameters[param]);
1023                                                         }
1024                                                 }
1025                                                 bool handled = false;
1026                                                 if (param>=pcnt)
1027                                                 {
1028                                                         // we're supposed to have a parameter, but none was given... so dont handle the mode.
1029                                                         if (((ModeDefinedOn(modechar,MT_CHANNEL)>0) && (mdir)) || ((ModeDefinedOff(modechar,MT_CHANNEL)>0) && (!mdir))) 
1030                                                         {
1031                                                                 log(DEBUG,"Not enough parameters for module-mode %c",modechar);
1032                                                                 handled = true;
1033                                                                 param++;
1034                                                         }
1035                                                 }
1036
1037                                                 // BIG ASS IDIOTIC CODER WARNING!
1038                                                 // Using OnRawMode on another modules mode's behavour 
1039                                                 // will confuse the crap out of admins! just because you CAN
1040                                                 // do it, doesnt mean you SHOULD!
1041                                                 MOD_RESULT = 0;
1042                                                 std::string para = "";
1043                                                 if (p.size())
1044                                                         para = p[0];
1045                                                 FOREACH_RESULT(OnRawMode(user, chan, modechar, para, mdir, pcnt));
1046                                                 if (!MOD_RESULT)
1047                                                 {
1048                                                         for (int i = 0; i <= MODCOUNT; i++)
1049                                                         {
1050                                                                 if (!handled)
1051                                                                 {
1052                                                                         int t = modules[i]->OnExtendedMode(user,chan,modechar,MT_CHANNEL,mdir,p);
1053                                                                         if (t != 0)
1054                                                                         {
1055                                                                                 log(DEBUG,"OnExtendedMode returned nonzero for a module");
1056                                                                                 char app[] = {modechar, 0};
1057                                                                                 if (ModeIsListMode(modechar,MT_CHANNEL))
1058                                                                                 {
1059                                                                                         if (t == -1)
1060                                                                                         {
1061                                                                                                 //pc++;
1062                                                                                                 param++;
1063                                                                                         }
1064                                                                                         else
1065                                                                                         {
1066                                                                                                 if (ptr>0)
1067                                                                                                 {
1068                                                                                                         strlcat(outlist, app,MAXBUF);
1069                                                                                                 }
1070                                                                                                 strlcpy(outpars[pc++],parameters[param++],MAXBUF);
1071                                                                                         }
1072                                                                                 }
1073                                                                                 else
1074                                                                                 {
1075                                                                                         if (ptr>0)
1076                                                                                         {
1077                                                                                                 if ((modelist[ptr-1] == '+') || (modelist[ptr-1] == '-'))
1078                                                                                                 {
1079                                                                                                         strlcat(outlist, app,MAXBUF);
1080                                                                                                 }
1081                                                                                                 else if (!strchr(outlist,modechar))
1082                                                                                                 {
1083                                                                                                         strlcat(outlist, app,MAXBUF);
1084                                                                                                 }
1085                                                                                         }
1086                                                                                         chan->SetCustomMode(modechar,mdir);
1087                                                                                         // include parameters in output if mode has them
1088                                                                                         if ((ModeDefinedOn(modechar,MT_CHANNEL)>0) && (mdir))
1089                                                                                         {
1090                                                                                                 chan->SetCustomModeParam(modelist[ptr],parameters[param],mdir);
1091                                                                                                 strlcpy(outpars[pc++],parameters[param++],MAXBUF);
1092                                                                                         }
1093                                                                                 }
1094                                                                                 // break, because only one module can handle the mode.
1095                                                                                 handled = true;
1096                                                                         }
1097                                                                 }
1098                                                         }
1099                                                 }
1100                                         }
1101                                         else
1102                                         {
1103                                                 WriteServ(user->fd,"472 %s %c :is unknown mode char to me",user->nick,modechar);
1104                                         }
1105                                 break;
1106                                 
1107                         }
1108                 }
1109         }
1110
1111         /* this ensures only the *valid* modes are sent out onto the network */
1112         int xt = strlen(outlist)-1;
1113         while ((outlist[xt] == '-') || (outlist[xt] == '+'))
1114         {
1115                 outlist[xt] = '\0';
1116                 xt = strlen(outlist)-1;
1117         }
1118         if (outlist[0])
1119         {
1120                 strlcpy(outstr,outlist,MAXBUF);
1121                 for (ptr = 0; ptr < pc; ptr++)
1122                 {
1123                         strlcat(outstr," ",MAXBUF);
1124                         strlcat(outstr,outpars[ptr],MAXBUF);
1125                 }
1126                 if (local)
1127                 {
1128                         log(DEBUG,"Local mode change");
1129                         WriteChannelLocal(chan, user, "MODE %s %s",chan->name,outstr);
1130                 }
1131                 else
1132                 {
1133                         if (servermode)
1134                         {
1135                                 if (!silent)
1136                                 {
1137                                         WriteChannelWithServ(ServerName,chan,"MODE %s %s",chan->name,outstr);
1138                                         // M token for a usermode must go to all servers
1139                                         char buffer[MAXBUF];
1140                                         snprintf(buffer,MAXBUF,"M %s %s",chan->name, outstr);
1141                                         NetSendToAll(buffer);
1142                                 }
1143                                         
1144                         }
1145                         else
1146                         {
1147                                 if (!silent)
1148                                 {
1149                                         WriteChannel(chan,user,"MODE %s %s",chan->name,outstr);
1150                                         // M token for a usermode must go to all servers
1151                                         char buffer[MAXBUF];
1152                                         snprintf(buffer,MAXBUF,"m %s %s %s",user->nick,chan->name, outstr);
1153                                         NetSendToAll(buffer);
1154                                 }
1155                         }
1156                 }
1157         }
1158 }
1159
1160 // based on sourcemodes, return true or false to determine if umode is a valid mode a user may set on themselves or others.
1161
1162 bool allowed_umode(char umode, char* sourcemodes,bool adding)
1163 {
1164         log(DEBUG,"Allowed_umode: %c %s",umode,sourcemodes);
1165         // RFC1459 specified modes
1166         if ((umode == 'w') || (umode == 's') || (umode == 'i'))
1167         {
1168                 log(DEBUG,"umode %c allowed by RFC1459 scemantics",umode);
1169                 return true;
1170         }
1171         
1172         // user may not +o themselves or others, but an oper may de-oper other opers or themselves
1173         if ((strchr(sourcemodes,'o')) && (!adding))
1174         {
1175                 log(DEBUG,"umode %c allowed by RFC1459 scemantics",umode);
1176                 return true;
1177         }
1178         else if (umode == 'o')
1179         {
1180                 log(DEBUG,"umode %c allowed by RFC1459 scemantics",umode);
1181                 return false;
1182         }
1183         
1184         // process any module-defined modes that need oper
1185         if ((ModeDefinedOper(umode,MT_CLIENT)) && (strchr(sourcemodes,'o')))
1186         {
1187                 log(DEBUG,"umode %c allowed by module handler (oper only mode)",umode);
1188                 return true;
1189         }
1190         else
1191         if (ModeDefined(umode,MT_CLIENT))
1192         {
1193                 // process any module-defined modes that don't need oper
1194                 log(DEBUG,"umode %c allowed by module handler (non-oper mode)",umode);
1195                 if ((ModeDefinedOper(umode,MT_CLIENT)) && (!strchr(sourcemodes,'o')))
1196                 {
1197                         // no, this mode needs oper, and this user 'aint got what it takes!
1198                         return false;
1199                 }
1200                 return true;
1201         }
1202
1203         // anything else - return false.
1204         log(DEBUG,"umode %c not known by any ruleset",umode);
1205         return false;
1206 }
1207
1208 bool process_module_umode(char umode, userrec* source, void* dest, bool adding)
1209 {
1210         userrec* s2;
1211         bool faked = false;
1212         if (!source)
1213         {
1214                 s2 = new userrec;
1215                 strlcpy(s2->nick,ServerName,NICKMAX);
1216                 strcpy(s2->modes,"o");
1217                 s2->fd = -1;
1218                 source = s2;
1219                 faked = true;
1220         }
1221         string_list p;
1222         p.clear();
1223         if (ModeDefined(umode,MT_CLIENT))
1224         {
1225                 for (int i = 0; i <= MODCOUNT; i++)
1226                 {
1227                         if (modules[i]->OnExtendedMode(source,(void*)dest,umode,MT_CLIENT,adding,p))
1228                         {
1229                                 log(DEBUG,"Module %s claims umode %c",module_names[i].c_str(),umode);
1230                                 return true;
1231                         }
1232                 }
1233                 log(DEBUG,"No module claims umode %c",umode);
1234                 if (faked)
1235                 {
1236                         delete s2;
1237                         source = NULL;
1238                 }
1239                 return false;
1240         }
1241         else
1242         {
1243                 if (faked)
1244                 {
1245                         delete s2;
1246                         source = NULL;
1247                 }
1248                 return false;
1249         }
1250 }
1251
1252 void handle_mode(char **parameters, int pcnt, userrec *user)
1253 {
1254         chanrec* Ptr;
1255         userrec* dest;
1256         int can_change;
1257         int direction = 1;
1258         char outpars[MAXBUF];
1259
1260         dest = Find(parameters[0]);
1261
1262         if (!user)
1263         {
1264                 return;
1265         }
1266
1267         if ((dest) && (pcnt == 1))
1268         {
1269                 WriteServ(user->fd,"221 %s :+%s",dest->nick,dest->modes);
1270                 return;
1271         }
1272
1273         if ((dest) && (pcnt > 1))
1274         {
1275                 std::string tidied = compress_modes(parameters[1],false);
1276                 parameters[1] = (char*)tidied.c_str();
1277
1278                 char dmodes[MAXBUF];
1279                 strlcpy(dmodes,dest->modes,MAXBUF);
1280                 log(DEBUG,"pulled up dest user modes: %s",dmodes);
1281
1282                 can_change = 0;
1283                 if (user != dest)
1284                 {
1285                         if (strchr(user->modes,'o'))
1286                         {
1287                                 can_change = 1;
1288                         }
1289                 }
1290                 else
1291                 {
1292                         can_change = 1;
1293                 }
1294                 if (!can_change)
1295                 {
1296                         WriteServ(user->fd,"482 %s :Can't change mode for other users",user->nick);
1297                         return;
1298                 }
1299                 
1300                 strcpy(outpars,"+");
1301                 direction = 1;
1302
1303                 if ((parameters[1][0] != '+') && (parameters[1][0] != '-'))
1304                         return;
1305
1306                 for (int i = 0; i < strlen(parameters[1]); i++)
1307                 {
1308                         if (parameters[1][i] == ' ')
1309                                 continue;
1310                         if (parameters[1][i] == '+')
1311                         {
1312                                 if (direction != 1)
1313                                 {
1314                                         int t = strlen(outpars)-1;
1315                                         if ((outpars[t] == '+') || (outpars[t] == '-'))
1316                                         {
1317                                                 outpars[t] = '+';
1318                                         }
1319                                         else
1320                                         {
1321                                                 strcat(outpars,"+");
1322                                         }
1323                                 }
1324                                 direction = 1;
1325                         }
1326                         else
1327                         if (parameters[1][i] == '-')
1328                         {
1329                                 if (direction != 0)
1330                                 {
1331                                         int t = strlen(outpars)-1;
1332                                         if ((outpars[t] == '+') || (outpars[t] == '-'))
1333                                         {
1334                                                 outpars[t] = '-';
1335                                         }
1336                                         else
1337                                         {
1338                                                 strcat(outpars,"-");
1339                                         }
1340                                 }
1341                                 direction = 0;
1342                         }
1343                         else
1344                         {
1345                                 can_change = 0;
1346                                 if (strchr(user->modes,'o'))
1347                                 {
1348                                         can_change = 1;
1349                                 }
1350                                 else
1351                                 {
1352                                         if ((parameters[1][i] == 'i') || (parameters[1][i] == 'w') || (parameters[1][i] == 's') || (allowed_umode(parameters[1][i],user->modes,direction)))
1353                                         {
1354                                                 can_change = 1;
1355                                         }
1356                                 }
1357                                 if (can_change)
1358                                 {
1359                                         if (direction == 1)
1360                                         {
1361                                                 if ((!strchr(dmodes,parameters[1][i])) && (allowed_umode(parameters[1][i],user->modes,true)))
1362                                                 {
1363                                                         char umode = parameters[1][i];
1364                                                         if ((process_module_umode(umode, user, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
1365                                                         {
1366                                                                 int q = strlen(dmodes);
1367                                                                 int r = strlen(outpars);
1368                                                                 dmodes[q+1]='\0';
1369                                                                 dmodes[q] = parameters[1][i];
1370                                                                 outpars[r+1]='\0';
1371                                                                 outpars[r] = parameters[1][i];
1372                                                                 if (parameters[1][i] == 'o')
1373                                                                 {
1374                                                                         FOREACH_MOD OnGlobalOper(dest);
1375                                                                 }
1376                                                         }
1377                                                 }
1378                                         }
1379                                         else
1380                                         {
1381                                                 if ((allowed_umode(parameters[1][i],user->modes,false)) && (strchr(dmodes,parameters[1][i])))
1382                                                 {
1383                                                         char umode = parameters[1][i];
1384                                                         if ((process_module_umode(umode, user, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
1385                                                         {
1386                                                                 int q = 0;
1387                                                                 char temp[MAXBUF];      
1388                                                                 char moo[MAXBUF];       
1389
1390                                                                 int r = strlen(outpars);
1391                                                                 outpars[r+1]='\0';
1392                                                                 outpars[r] = parameters[1][i];
1393                                                         
1394                                                                 strcpy(temp,"");
1395                                                                 for (q = 0; q < strlen(dmodes); q++)
1396                                                                 {
1397                                                                         if (dmodes[q] != parameters[1][i])
1398                                                                         {
1399                                                                                 moo[0] = dmodes[q];
1400                                                                                 moo[1] = '\0';
1401                                                                                 strlcat(temp,moo,MAXBUF);
1402                                                                         }
1403                                                                 }
1404                                                                 strlcpy(dmodes,temp,MAXBUF);
1405
1406                                                                 if (umode == 'o')
1407                                                                         DeleteOper(dest);
1408                                                         }
1409                                                 }
1410                                         }
1411                                 }
1412                         }
1413                 }
1414                 if (outpars[0])
1415                 {
1416                         char b[MAXBUF];
1417                         strlcpy(b,"",MAXBUF);
1418                         int z = 0;
1419                         int i = 0;
1420                         while (i < strlen (outpars))
1421                         {
1422                                 b[z++] = outpars[i++];
1423                                 b[z] = '\0';
1424                                 if (i<strlen(outpars)-1)
1425                                 {
1426                                         if (((outpars[i] == '-') || (outpars[i] == '+')) && ((outpars[i+1] == '-') || (outpars[i+1] == '+')))
1427                                         {
1428                                                 // someones playing silly buggers and trying
1429                                                 // to put a +- or -+ into the line...
1430                                                 i++;
1431                                         }
1432                                 }
1433                                 if (i == strlen(outpars)-1)
1434                                 {
1435                                         if ((outpars[i] == '-') || (outpars[i] == '+'))
1436                                         {
1437                                                 i++;
1438                                         }
1439                                 }
1440                         }
1441
1442                         z = strlen(b)-1;
1443                         if ((b[z] == '-') || (b[z] == '+'))
1444                                 b[z] = '\0';
1445
1446                         if ((!b[0]) || (!strcmp(b,"+")) || (!strcmp(b,"-")))
1447                                 return;
1448
1449                         if (strcmp(b,""))
1450                         {
1451                                 WriteTo(user, dest, "MODE %s :%s", dest->nick, b);
1452                                 // M token for a usermode must go to all servers
1453                                 char buffer[MAXBUF];
1454                                 snprintf(buffer,MAXBUF,"m %s %s %s",user->nick, dest->nick, b);
1455                                 NetSendToAll(buffer);
1456                         }
1457
1458                         if (strlen(dmodes)>MAXMODES)
1459                         {
1460                                 dmodes[MAXMODES-1] = '\0';
1461                         }
1462                         log(DEBUG,"Stripped mode line");
1463                         log(DEBUG,"Line dest is now %s",dmodes);
1464                         strlcpy(dest->modes,dmodes,MAXMODES);
1465
1466                 }
1467
1468                 return;
1469         }
1470         
1471         Ptr = FindChan(parameters[0]);
1472         if (Ptr)
1473         {
1474                 if (pcnt == 1)
1475                 {
1476                         /* just /modes #channel */
1477                         WriteServ(user->fd,"324 %s %s +%s",user->nick, Ptr->name, chanmodes(Ptr));
1478                         WriteServ(user->fd,"329 %s %s %d", user->nick, Ptr->name, Ptr->created);
1479                         return;
1480                 }
1481                 else
1482                 if (pcnt == 2)
1483                 {
1484                         char* mode = parameters[1];
1485                         if (*mode == '+')
1486                                 mode++;
1487                         int MOD_RESULT = 0;
1488                         FOREACH_RESULT(OnRawMode(user, Ptr, *mode, "", false, 0));
1489                         if (!MOD_RESULT)
1490                         {
1491                                 if (*mode == 'b')
1492                                 {
1493
1494                                         for (BanList::iterator i = Ptr->bans.begin(); i != Ptr->bans.end(); i++)
1495                                         {
1496                                                 WriteServ(user->fd,"367 %s %s %s %s %d",user->nick, Ptr->name, i->data, i->set_by, i->set_time);
1497                                         }
1498                                         WriteServ(user->fd,"368 %s %s :End of channel ban list",user->nick, Ptr->name);
1499                                         return;
1500                                 }
1501                                 if ((ModeDefined(*mode,MT_CHANNEL)) && (ModeIsListMode(*mode,MT_CHANNEL)))
1502                                 {
1503                                         // list of items for an extmode
1504                                         log(DEBUG,"Calling OnSendList for all modules, list output for mode %c",*mode);
1505                                         FOREACH_MOD OnSendList(user,Ptr,*mode);
1506                                         return;
1507                                 }
1508                         }
1509                 }
1510
1511                 if ((Ptr) && (!has_channel(user,Ptr)))
1512                 {
1513                         WriteServ(user->fd,"442 %s %s :You're not on that channel!",user->nick, Ptr->name);
1514                         return;
1515                 }
1516
1517                 if (Ptr)
1518                 {
1519                         int MOD_RESULT = 0;
1520                         FOREACH_RESULT(OnAccessCheck(user,NULL,Ptr,AC_GENERAL_MODE));
1521                         
1522                         if (MOD_RESULT == ACR_DENY)
1523                                 return;
1524                         if (MOD_RESULT == ACR_DEFAULT)
1525                         {
1526                                 if (cstatus(user,Ptr) < STATUS_HOP)
1527                                 {
1528                                         WriteServ(user->fd,"482 %s %s :You must be at least a half-operator to change modes on this channel",user->nick, Ptr->name);
1529                                         return;
1530                                 }
1531                         }
1532
1533                         process_modes(parameters,user,Ptr,cstatus(user,Ptr),pcnt,false,false,false);
1534                 }
1535         }
1536         else
1537         {
1538                 WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, parameters[0]);
1539         }
1540 }
1541
1542
1543
1544
1545 void server_mode(char **parameters, int pcnt, userrec *user)
1546 {
1547         chanrec* Ptr;
1548         userrec* dest;
1549         int can_change;
1550         int direction = 1;
1551         char outpars[MAXBUF];
1552
1553         dest = Find(parameters[0]);
1554         
1555         // fix: ChroNiCk found this - we cant use this as debug if its null!
1556         if (dest)
1557         {
1558                 log(DEBUG,"server_mode on %s",dest->nick);
1559         }
1560
1561         if ((dest) && (pcnt > 1))
1562         {
1563                 std::string tidied = compress_modes(parameters[1],false);
1564                 parameters[1] = (char*)tidied.c_str();
1565
1566                 char dmodes[MAXBUF];
1567                 strlcpy(dmodes,dest->modes,MAXBUF);
1568
1569                 strcpy(outpars,"+");
1570                 direction = 1;
1571
1572                 if ((parameters[1][0] != '+') && (parameters[1][0] != '-'))
1573                         return;
1574
1575                 for (int i = 0; i < strlen(parameters[1]); i++)
1576                 {
1577                         if (parameters[1][i] == ' ')
1578                                 continue;
1579                         if (parameters[1][i] == '+')
1580                         {
1581                                 if (direction != 1)
1582                                 {
1583                                         int t = strlen(outpars)-1;
1584                                         if ((outpars[t] == '+') || (outpars[t] == '-'))
1585                                         {
1586                                                 outpars[t] = '+';
1587                                         }
1588                                         else
1589                                         {
1590                                                 strcat(outpars,"+");
1591                                         }
1592                                 }
1593                                 direction = 1;
1594                         }
1595                         else
1596                         if (parameters[1][i] == '-')
1597                         {
1598                                 if (direction != 0)
1599                                 {
1600                                         int t = strlen(outpars)-1;
1601                                         if ((outpars[t] == '+') || (outpars[t] == '-'))
1602                                         {
1603                                                 outpars[t] = '-';
1604                                         }
1605                                         else
1606                                         {
1607                                                 strcat(outpars,"-");
1608                                         }
1609                                 }
1610                                 direction = 0;
1611                         }
1612                         else
1613                         {
1614                                 log(DEBUG,"begin mode processing entry");
1615                                 can_change = 1;
1616                                 if (can_change)
1617                                 {
1618                                         if (direction == 1)
1619                                         {
1620                                                 log(DEBUG,"umode %c being added",parameters[1][i]);
1621                                                 if ((!strchr(dmodes,parameters[1][i])) && (allowed_umode(parameters[1][i],user->modes,true)))
1622                                                 {
1623                                                         char umode = parameters[1][i];
1624                                                         log(DEBUG,"umode %c is an allowed umode",umode);
1625                                                         if ((process_module_umode(umode, user, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
1626                                                         {
1627                                                                 int v1 = strlen(dmodes);
1628                                                                 int v2 = strlen(outpars);
1629                                                                 dmodes[v1+1]='\0';
1630                                                                 dmodes[v1] = parameters[1][i];
1631                                                                 outpars[v2+1]='\0';
1632                                                                 outpars[v2] = parameters[1][i];
1633                                                         }
1634                                                 }
1635                                         }
1636                                         else
1637                                         {
1638                                                 // can only remove a mode they already have
1639                                                 log(DEBUG,"umode %c being removed",parameters[1][i]);
1640                                                 if ((allowed_umode(parameters[1][i],user->modes,false)) && (strchr(dmodes,parameters[1][i])))
1641                                                 {
1642                                                         char umode = parameters[1][i];
1643                                                         log(DEBUG,"umode %c is an allowed umode",umode);
1644                                                         if ((process_module_umode(umode, user, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
1645                                                         {
1646                                                                 int q = 0;
1647                                                                 char temp[MAXBUF];
1648                                                                 char moo[MAXBUF];       
1649
1650                                                                 int v1 = strlen(outpars);
1651                                                                 outpars[v1+1]='\0';
1652                                                                 outpars[v1] = parameters[1][i];
1653                                                         
1654                                                                 strcpy(temp,"");
1655                                                                 for (q = 0; q < strlen(dmodes); q++)
1656                                                                 {
1657                                                                         if (dmodes[q] != parameters[1][i])
1658                                                                         {
1659                                                                                 moo[0] = dmodes[q];
1660                                                                                 moo[1] = '\0';
1661                                                                                 strlcat(temp,moo,MAXBUF);
1662                                                                         }
1663                                                                 }
1664                                                                 strlcpy(dmodes,temp,MAXBUF);
1665                                                         }
1666                                                 }
1667                                         }
1668                                 }
1669                         }
1670                 }
1671                 if (outpars[0])
1672                 {
1673                         char b[MAXBUF];
1674                         strlcpy(b,"",MAXBUF);
1675                         int z = 0;
1676                         int i = 0;
1677                         while (i < strlen (outpars))
1678                         {
1679                                 b[z++] = outpars[i++];
1680                                 b[z] = '\0';
1681                                 if (i<strlen(outpars)-1)
1682                                 {
1683                                         if (((outpars[i] == '-') || (outpars[i] == '+')) && ((outpars[i+1] == '-') || (outpars[i+1] == '+')))
1684                                         {
1685                                                 // someones playing silly buggers and trying
1686                                                 // to put a +- or -+ into the line...
1687                                                 i++;
1688                                         }
1689                                 }
1690                                 if (i == strlen(outpars)-1)
1691                                 {
1692                                         if ((outpars[i] == '-') || (outpars[i] == '+'))
1693                                         {
1694                                                 i++;
1695                                         }
1696                                 }
1697                         }
1698
1699                         z = strlen(b)-1;
1700                         if ((b[z] == '-') || (b[z] == '+'))
1701                                 b[z] = '\0';
1702
1703                         if ((!b[0]) || (!strcmp(b,"+")) || (!strcmp(b,"-")))
1704                                 return;
1705
1706                         if (strcmp(b,""))
1707                         {
1708                                 WriteTo(user, dest, "MODE %s :%s", dest->nick, b);
1709                                 // M token for a usermode must go to all servers
1710                                 char buffer[MAXBUF];
1711                                 snprintf(buffer,MAXBUF,"m %s %s %s",user->nick, dest->nick, b);
1712                                 NetSendToAll(buffer);
1713                         }
1714                         
1715                         if (strlen(dmodes)>MAXMODES)
1716                         {
1717                                 dmodes[MAXMODES-1] = '\0';
1718                         }
1719                         log(DEBUG,"Stripped mode line");
1720                         log(DEBUG,"Line dest is now %s",dmodes);
1721                         strlcpy(dest->modes,dmodes,MAXMODES);
1722
1723                 }
1724
1725                 return;
1726         }
1727         
1728         Ptr = FindChan(parameters[0]);
1729         if (Ptr)
1730         {
1731                 process_modes(parameters,user,Ptr,STATUS_OP,pcnt,true,false,false);
1732         }
1733         else
1734         {
1735                 WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, parameters[0]);
1736         }
1737 }
1738
1739
1740
1741 void merge_mode(char **parameters, int pcnt)
1742 {
1743         chanrec* Ptr;
1744         userrec* dest;
1745         int can_change;
1746         int direction = 1;
1747         char outpars[MAXBUF];
1748
1749         dest = Find(parameters[0]);
1750         
1751         // fix: ChroNiCk found this - we cant use this as debug if its null!
1752         if (dest)
1753         {
1754                 log(DEBUG,"merge_mode on %s",dest->nick);
1755         }
1756
1757         if ((dest) && (pcnt > 1))
1758         {
1759                 std::string tidied = compress_modes(parameters[1],false);
1760                 parameters[1] = (char*)tidied.c_str();
1761
1762                 char dmodes[MAXBUF];
1763                 strlcpy(dmodes,dest->modes,MAXBUF);
1764
1765                 strcpy(outpars,"+");
1766                 direction = 1;
1767
1768                 if ((parameters[1][0] != '+') && (parameters[1][0] != '-'))
1769                         return;
1770
1771                 for (int i = 0; i < strlen(parameters[1]); i++)
1772                 {
1773                         if (parameters[1][i] == ' ')
1774                                 continue;
1775                         if (parameters[1][i] == '+')
1776                         {
1777                                 if (direction != 1)
1778                                 {
1779                                         int t = strlen(outpars)-1;
1780                                         if ((outpars[t] == '+') || (outpars[t] == '-'))
1781                                         {
1782                                                 outpars[t] = '+';
1783                                         }
1784                                         else
1785                                         {
1786                                                 strcat(outpars,"+");
1787                                         }
1788                                 }
1789                                 direction = 1;
1790                         }
1791                         else
1792                         if (parameters[1][i] == '-')
1793                         {
1794                                 if (direction != 0)
1795                                 {
1796                                         int t = strlen(outpars)-1;
1797                                         if ((outpars[t] == '+') || (outpars[t] == '-'))
1798                                         {
1799                                                 outpars[t] = '-';
1800                                         }
1801                                         else
1802                                         {
1803                                                 strcat(outpars,"-");
1804                                         }
1805                                 }
1806                                 direction = 0;
1807                         }
1808                         else
1809                         {
1810                                 log(DEBUG,"begin mode processing entry");
1811                                 can_change = 1;
1812                                 if (can_change)
1813                                 {
1814                                         if (direction == 1)
1815                                         {
1816                                                 log(DEBUG,"umode %c being added",parameters[1][i]);
1817                                                 if ((!strchr(dmodes,parameters[1][i])) && (allowed_umode(parameters[1][i],"o",true)))
1818                                                 {
1819                                                         char umode = parameters[1][i];
1820                                                         log(DEBUG,"umode %c is an allowed umode",umode);
1821                                                         if ((process_module_umode(umode, NULL, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
1822                                                         {
1823                                                                 int v1 = strlen(dmodes);
1824                                                                 int v2 = strlen(outpars);
1825                                                                 dmodes[v1+1]='\0';
1826                                                                 dmodes[v1] = parameters[1][i];
1827                                                                 outpars[v2+1]='\0';
1828                                                                 outpars[v2] = parameters[1][i];
1829                                                         }
1830                                                 }
1831                                         }
1832                                         else
1833                                         {
1834                                                 // can only remove a mode they already have
1835                                                 log(DEBUG,"umode %c being removed",parameters[1][i]);
1836                                                 if ((allowed_umode(parameters[1][i],"o",false)) && (strchr(dmodes,parameters[1][i])))
1837                                                 {
1838                                                         char umode = parameters[1][i];
1839                                                         log(DEBUG,"umode %c is an allowed umode",umode);
1840                                                         if ((process_module_umode(umode, NULL, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
1841                                                         {
1842                                                                 int q = 0;
1843                                                                 char temp[MAXBUF];
1844                                                                 char moo[MAXBUF];       
1845
1846                                                                 int v1 = strlen(outpars);
1847                                                                 outpars[v1+1]='\0';
1848                                                                 outpars[v1] = parameters[1][i];
1849                                                         
1850                                                                 strcpy(temp,"");
1851                                                                 for (q = 0; q < strlen(dmodes); q++)
1852                                                                 {
1853                                                                         if (dmodes[q] != parameters[1][i])
1854                                                                         {
1855                                                                                 moo[0] = dmodes[q];
1856                                                                                 moo[1] = '\0';
1857                                                                                 strlcat(temp,moo,MAXBUF);
1858                                                                         }
1859                                                                 }
1860                                                                 strlcpy(dmodes,temp,MAXBUF);
1861                                                         }
1862                                                 }
1863                                         }
1864                                 }
1865                         }
1866                 }
1867                 if (outpars[0])
1868                 {
1869                         char b[MAXBUF];
1870                         strcpy(b,"");
1871                         int z = 0;
1872                         int i = 0;
1873                         while (i < strlen (outpars))
1874                         {
1875                                 b[z++] = outpars[i++];
1876                                 b[z] = '\0';
1877                                 if (i<strlen(outpars)-1)
1878                                 {
1879                                         if (((outpars[i] == '-') || (outpars[i] == '+')) && ((outpars[i+1] == '-') || (outpars[i+1] == '+')))
1880                                         {
1881                                                 // someones playing silly buggers and trying
1882                                                 // to put a +- or -+ into the line...
1883                                                 i++;
1884                                         }
1885                                 }
1886                                 if (i == strlen(outpars)-1)
1887                                 {
1888                                         if ((outpars[i] == '-') || (outpars[i] == '+'))
1889                                         {
1890                                                 i++;
1891                                         }
1892                                 }
1893                         }
1894
1895                         z = strlen(b)-1;
1896                         if ((b[z] == '-') || (b[z] == '+'))
1897                                 b[z] = '\0';
1898
1899                         if ((!strcmp(b,"+")) || (!strcmp(b,"-")))
1900                                 return;
1901
1902                         if (strlen(dmodes)>MAXMODES)
1903                         {
1904                                 dmodes[MAXMODES-1] = '\0';
1905                         }
1906                         log(DEBUG,"Stripped mode line");
1907                         log(DEBUG,"Line dest is now %s",dmodes);
1908                         strlcpy(dest->modes,dmodes,MAXMODES);
1909
1910                 }
1911
1912                 return;
1913         }
1914         
1915         Ptr = FindChan(parameters[0]);
1916         if (Ptr)
1917         {
1918                 userrec s2;
1919                 strlcpy(s2.nick,ServerName,NICKMAX);
1920                 strcpy(s2.modes,"o");
1921                 s2.fd = -1;
1922                 process_modes(parameters,&s2,Ptr,STATUS_OP,pcnt,true,true,false);
1923         }
1924 }
1925
1926
1927 void merge_mode2(char **parameters, int pcnt, userrec* user)
1928 {
1929         chanrec* Ptr;
1930         userrec* dest;
1931         int can_change;
1932         int direction = 1;
1933         char outpars[MAXBUF];
1934
1935         dest = Find(parameters[0]);
1936         
1937         // fix: ChroNiCk found this - we cant use this as debug if its null!
1938         if (dest)
1939         {
1940                 log(DEBUG,"merge_mode2 on %s",dest->nick);
1941         }
1942
1943         if ((dest) && (pcnt > 1))
1944         {
1945                 std::string tidied = compress_modes(parameters[1],false);
1946                 parameters[1] = (char*)tidied.c_str();
1947
1948                 char dmodes[MAXBUF];
1949                 strlcpy(dmodes,dest->modes,MAXBUF);
1950
1951                 strcpy(outpars,"+");
1952                 direction = 1;
1953
1954                 if ((parameters[1][0] == ':') && (strlen(parameters[1])>1))
1955                 {
1956                         // some stupid 3rd party things (such as services packages) put a colon on the mode list...
1957                         log(DEBUG,"Some muppet put a colon on the modelist! changed to '%s'",++parameters[1]);
1958                 }
1959                 if ((parameters[1][0] != '+') && (parameters[1][0] != '-'))
1960                 return;
1961
1962                 for (int i = 0; i < strlen(parameters[1]); i++)
1963                 {
1964                         if (parameters[1][i] == ' ')
1965                                 continue;
1966                         if (parameters[1][i] == '+')
1967                         {
1968                                 if (direction != 1)
1969                                 {
1970                                         int t = strlen(outpars)-1;
1971                                         if ((outpars[t] == '+') || (outpars[t] == '-'))
1972                                         {
1973                                                 outpars[t] = '+';
1974                                         }
1975                                         else
1976                                         {
1977                                                 strcat(outpars,"+");
1978                                         }
1979                                 }
1980                                 direction = 1;
1981                         }
1982                         else
1983                         if (parameters[1][i] == '-')
1984                         {
1985                                 if (direction != 0)
1986                                 {
1987                                         int t = strlen(outpars)-1;
1988                                         if ((outpars[t] == '+') || (outpars[t] == '-'))
1989                                         {
1990                                                 outpars[t] = '-';
1991                                         }
1992                                         else
1993                                         {
1994                                                 strcat(outpars,"-");
1995                                         }
1996                                 }
1997                                 direction = 0;
1998                         }
1999                         else
2000                         {
2001                                 log(DEBUG,"begin mode processing entry");
2002                                 can_change = 1;
2003                                 if (can_change)
2004                                 {
2005                                         if (direction == 1)
2006                                         {
2007                                                 log(DEBUG,"umode %c being added",parameters[1][i]);
2008                                                 if ((!strchr(dmodes,parameters[1][i])) && (allowed_umode(parameters[1][i],user->modes,true)))
2009                                                 {
2010                                                         char umode = parameters[1][i];
2011                                                         log(DEBUG,"umode %c is an allowed umode",umode);
2012                                                         if ((process_module_umode(umode, NULL, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
2013                                                         {
2014                                                                 int v1 = strlen(dmodes);
2015                                                                 int v2 = strlen(outpars);
2016                                                                 dmodes[v1+1]='\0';
2017                                                                 dmodes[v1] = parameters[1][i];
2018                                                                 outpars[v2+1]='\0';
2019                                                                 outpars[v2] = parameters[1][i];
2020                                                                 log(DEBUG,"OUTPARS='%s', DMODES='%s'",outpars,dmodes);
2021                                                         }
2022                                                 }
2023                                         }
2024                                         else
2025                                         {
2026                                                 // can only remove a mode they already have
2027                                                 log(DEBUG,"umode %c being removed",parameters[1][i]);
2028                                                 if ((allowed_umode(parameters[1][i],user->modes,false)) && (strchr(dmodes,parameters[1][i])))
2029                                                 {
2030                                                         char umode = parameters[1][i];
2031                                                         log(DEBUG,"umode %c is an allowed umode",umode);
2032                                                         if ((process_module_umode(umode, NULL, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
2033                                                         {
2034                                                                 int q = 0;
2035                                                                 char temp[MAXBUF];
2036                                                                 char moo[MAXBUF];       
2037
2038                                                                 int v1 = strlen(outpars);
2039                                                                 outpars[v1+1]='\0';
2040                                                                 outpars[v1] = parameters[1][i];
2041                                                         
2042                                                                 strcpy(temp,"");
2043                                                                 for (q = 0; q < strlen(dmodes); q++)
2044                                                                 {
2045                                                                         if (dmodes[q] != parameters[1][i])
2046                                                                         {
2047                                                                                 moo[0] = dmodes[q];
2048                                                                                 moo[1] = '\0';
2049                                                                                 strlcat(temp,moo,MAXBUF);
2050                                                                         }
2051                                                                 }
2052                                                                 strlcpy(dmodes,temp,MAXBUF);
2053                                                         }
2054                                                 }
2055                                         }
2056                                 }
2057                         }
2058                 }
2059                 log(DEBUG,"DONE! OUTPARS='%s', DMODES='%s'",outpars,dmodes);
2060                 if (outpars[0])
2061                 {
2062                         char b[MAXBUF];
2063                         strcpy(b,"");
2064                         int z = 0;
2065                         int i = 0;
2066                         while (i < strlen (outpars))
2067                         {
2068                                 b[z++] = outpars[i++];
2069                                 b[z] = '\0';
2070                                 if (i<strlen(outpars)-1)
2071                                 {
2072                                         if (((outpars[i] == '-') || (outpars[i] == '+')) && ((outpars[i+1] == '-') || (outpars[i+1] == '+')))
2073                                         {
2074                                                 // someones playing silly buggers and trying
2075                                                 // to put a +- or -+ into the line...
2076                                                 i++;
2077                                         }
2078                                 }
2079                                 if (i == strlen(outpars)-1)
2080                                 {
2081                                         if ((outpars[i] == '-') || (outpars[i] == '+'))
2082                                         {
2083                                                 i++;
2084                                         }
2085                                 }
2086                         }
2087
2088                         z = strlen(b)-1;
2089                         if ((b[z] == '-') || (b[z] == '+'))
2090                                 b[z] = '\0';
2091
2092
2093                         if ((!b[0]) || (!strcmp(b,"+")) || (!strcmp(b,"-")))
2094                                 return;
2095
2096                         if (strcmp(b,""))
2097                         {
2098                                 WriteTo(user,dest,"MODE %s :%s",dest->nick,b);
2099                                 log(DEBUG,"Sent: :%s MODE %s",user->nick,b);
2100                         }
2101
2102                         if (strlen(dmodes)>MAXMODES)
2103                         {
2104                                 dmodes[MAXMODES-1] = '\0';
2105                         }
2106                         log(DEBUG,"Stripped mode line");
2107                         log(DEBUG,"Line dest is now %s",dmodes);
2108                         strlcpy(dest->modes,dmodes,MAXMODES);
2109                 }
2110
2111                 return;
2112         }
2113         
2114         Ptr = FindChan(parameters[0]);
2115         if (Ptr)
2116         {
2117                 log(DEBUG,"merge_mode2: found channel %s",Ptr->name);
2118                 if (Ptr)
2119                 {
2120                         if ((cstatus(user,Ptr) < STATUS_HOP) && (!is_uline(user->server)))
2121                         {
2122                                 return;
2123                         }
2124                         process_modes(parameters,user,Ptr,cstatus(user,Ptr),pcnt,false,false,true);
2125                 }
2126         }
2127 }
2128
2129