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