]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/mode.cpp
57db1d509492d20da08fbb82f9b3efc791510b63
[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)
1177 {
1178         log(DEBUG,"Allowed_umode: %c %s",umode,sourcemodes);
1179         // RFC1459 specified modes
1180         if ((umode == 'w') || (umode == 's') || (umode == 'i'))
1181         {
1182                 log(DEBUG,"umode %c allowed by RFC1459 scemantics",umode);
1183                 return true;
1184         }
1185         
1186         // user may not +o themselves or others, but an oper may de-oper other opers or themselves
1187         if ((strchr(sourcemodes,'o')) && (!adding))
1188         {
1189                 log(DEBUG,"umode %c allowed by RFC1459 scemantics",umode);
1190                 return true;
1191         }
1192         else if (umode == 'o')
1193         {
1194                 log(DEBUG,"umode %c allowed by RFC1459 scemantics",umode);
1195                 return false;
1196         }
1197         
1198         // process any module-defined modes that need oper
1199         if ((ModeDefinedOper(umode,MT_CLIENT)) && (strchr(sourcemodes,'o')))
1200         {
1201                 log(DEBUG,"umode %c allowed by module handler (oper only mode)",umode);
1202                 return true;
1203         }
1204         else
1205         if (ModeDefined(umode,MT_CLIENT))
1206         {
1207                 // process any module-defined modes that don't need oper
1208                 log(DEBUG,"umode %c allowed by module handler (non-oper mode)",umode);
1209                 if ((ModeDefinedOper(umode,MT_CLIENT)) && (!strchr(sourcemodes,'o')))
1210                 {
1211                         // no, this mode needs oper, and this user 'aint got what it takes!
1212                         return false;
1213                 }
1214                 return true;
1215         }
1216
1217         // anything else - return false.
1218         log(DEBUG,"umode %c not known by any ruleset",umode);
1219         return false;
1220 }
1221
1222 bool process_module_umode(char umode, userrec* source, void* dest, bool adding)
1223 {
1224         userrec* s2;
1225         bool faked = false;
1226         if (!source)
1227         {
1228                 s2 = new userrec;
1229                 strlcpy(s2->nick,ServerName,NICKMAX);
1230                 strlcpy(s2->modes,"o",52);
1231                 s2->fd = -1;
1232                 source = s2;
1233                 faked = true;
1234         }
1235         string_list p;
1236         p.clear();
1237         if (ModeDefined(umode,MT_CLIENT))
1238         {
1239                 for (int i = 0; i <= MODCOUNT; i++)
1240                 {
1241                         if (modules[i]->OnExtendedMode(source,(void*)dest,umode,MT_CLIENT,adding,p))
1242                         {
1243                                 log(DEBUG,"Module %s claims umode %c",module_names[i].c_str(),umode);
1244                                 return true;
1245                         }
1246                 }
1247                 log(DEBUG,"No module claims umode %c",umode);
1248                 if (faked)
1249                 {
1250                         delete s2;
1251                         source = NULL;
1252                 }
1253                 return false;
1254         }
1255         else
1256         {
1257                 if (faked)
1258                 {
1259                         delete s2;
1260                         source = NULL;
1261                 }
1262                 return false;
1263         }
1264 }
1265
1266 void handle_mode(char **parameters, int pcnt, userrec *user)
1267 {
1268         chanrec* Ptr;
1269         userrec* dest;
1270         int can_change;
1271         int direction = 1;
1272         char outpars[MAXBUF];
1273
1274         dest = Find(parameters[0]);
1275
1276         if (!user)
1277         {
1278                 return;
1279         }
1280
1281         if ((dest) && (pcnt == 1))
1282         {
1283                 WriteServ(user->fd,"221 %s :+%s",dest->nick,dest->modes);
1284                 return;
1285         }
1286
1287         if ((dest) && (pcnt > 1))
1288         {
1289                 std::string tidied = compress_modes(parameters[1],false);
1290                 parameters[1] = (char*)tidied.c_str();
1291
1292                 char dmodes[MAXBUF];
1293                 strlcpy(dmodes,dest->modes,52);
1294                 log(DEBUG,"pulled up dest user modes: %s",dmodes);
1295
1296                 can_change = 0;
1297                 if (user != dest)
1298                 {
1299                         if (strchr(user->modes,'o'))
1300                         {
1301                                 can_change = 1;
1302                         }
1303                 }
1304                 else
1305                 {
1306                         can_change = 1;
1307                 }
1308                 if (!can_change)
1309                 {
1310                         WriteServ(user->fd,"482 %s :Can't change mode for other users",user->nick);
1311                         return;
1312                 }
1313                 
1314                 strcpy(outpars,"+");
1315                 direction = 1;
1316
1317                 if ((parameters[1][0] != '+') && (parameters[1][0] != '-'))
1318                         return;
1319
1320                 for (unsigned int i = 0; i < strlen(parameters[1]); i++)
1321                 {
1322                         if (parameters[1][i] == ' ')
1323                                 continue;
1324                         if (parameters[1][i] == '+')
1325                         {
1326                                 if (direction != 1)
1327                                 {
1328                                         int t = strlen(outpars)-1;
1329                                         if ((outpars[t] == '+') || (outpars[t] == '-'))
1330                                         {
1331                                                 outpars[t] = '+';
1332                                         }
1333                                         else
1334                                         {
1335                                                 strcat(outpars,"+");
1336                                         }
1337                                 }
1338                                 direction = 1;
1339                         }
1340                         else
1341                         if (parameters[1][i] == '-')
1342                         {
1343                                 if (direction != 0)
1344                                 {
1345                                         int t = strlen(outpars)-1;
1346                                         if ((outpars[t] == '+') || (outpars[t] == '-'))
1347                                         {
1348                                                 outpars[t] = '-';
1349                                         }
1350                                         else
1351                                         {
1352                                                 strcat(outpars,"-");
1353                                         }
1354                                 }
1355                                 direction = 0;
1356                         }
1357                         else
1358                         {
1359                                 can_change = 0;
1360                                 if (strchr(user->modes,'o'))
1361                                 {
1362                                         can_change = 1;
1363                                 }
1364                                 else
1365                                 {
1366                                         if ((parameters[1][i] == 'i') || (parameters[1][i] == 'w') || (parameters[1][i] == 's') || (allowed_umode(parameters[1][i],user->modes,direction)))
1367                                         {
1368                                                 can_change = 1;
1369                                         }
1370                                 }
1371                                 if (can_change)
1372                                 {
1373                                         if (direction == 1)
1374                                         {
1375                                                 if ((!strchr(dmodes,parameters[1][i])) && (allowed_umode(parameters[1][i],user->modes,true)))
1376                                                 {
1377                                                         char umode = parameters[1][i];
1378                                                         if ((process_module_umode(umode, user, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
1379                                                         {
1380                                                                 int q = strlen(dmodes);
1381                                                                 int r = strlen(outpars);
1382                                                                 dmodes[q+1]='\0';
1383                                                                 dmodes[q] = parameters[1][i];
1384                                                                 outpars[r+1]='\0';
1385                                                                 outpars[r] = parameters[1][i];
1386                                                                 if (parameters[1][i] == 'o')
1387                                                                 {
1388                                                                         FOREACH_MOD OnGlobalOper(dest);
1389                                                                 }
1390                                                         }
1391                                                 }
1392                                         }
1393                                         else
1394                                         {
1395                                                 if ((allowed_umode(parameters[1][i],user->modes,false)) && (strchr(dmodes,parameters[1][i])))
1396                                                 {
1397                                                         char umode = parameters[1][i];
1398                                                         if ((process_module_umode(umode, user, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
1399                                                         {
1400                                                                 unsigned int q = 0;
1401                                                                 char temp[MAXBUF];      
1402                                                                 char moo[MAXBUF];       
1403
1404                                                                 unsigned int r = strlen(outpars);
1405                                                                 outpars[r+1]='\0';
1406                                                                 outpars[r] = parameters[1][i];
1407                                                         
1408                                                                 strcpy(temp,"");
1409                                                                 for (q = 0; q < strlen(dmodes); q++)
1410                                                                 {
1411                                                                         if (dmodes[q] != parameters[1][i])
1412                                                                         {
1413                                                                                 moo[0] = dmodes[q];
1414                                                                                 moo[1] = '\0';
1415                                                                                 strlcat(temp,moo,MAXBUF);
1416                                                                         }
1417                                                                 }
1418                                                                 strlcpy(dmodes,temp,52);
1419
1420                                                                 if (umode == 'o')
1421                                                                         DeleteOper(dest);
1422                                                         }
1423                                                 }
1424                                         }
1425                                 }
1426                         }
1427                 }
1428                 if (outpars[0])
1429                 {
1430                         char b[MAXBUF];
1431                         strlcpy(b,"",MAXBUF);
1432                         unsigned int z = 0;
1433                         unsigned int i = 0;
1434                         while (i < strlen (outpars))
1435                         {
1436                                 b[z++] = outpars[i++];
1437                                 b[z] = '\0';
1438                                 if (i<strlen(outpars)-1)
1439                                 {
1440                                         if (((outpars[i] == '-') || (outpars[i] == '+')) && ((outpars[i+1] == '-') || (outpars[i+1] == '+')))
1441                                         {
1442                                                 // someones playing silly buggers and trying
1443                                                 // to put a +- or -+ into the line...
1444                                                 i++;
1445                                         }
1446                                 }
1447                                 if (i == strlen(outpars)-1)
1448                                 {
1449                                         if ((outpars[i] == '-') || (outpars[i] == '+'))
1450                                         {
1451                                                 i++;
1452                                         }
1453                                 }
1454                         }
1455
1456                         z = strlen(b)-1;
1457                         if ((b[z] == '-') || (b[z] == '+'))
1458                                 b[z] = '\0';
1459
1460                         if ((!b[0]) || (!strcmp(b,"+")) || (!strcmp(b,"-")))
1461                                 return;
1462
1463                         if (strcmp(b,""))
1464                         {
1465                                 WriteTo(user, dest, "MODE %s :%s", dest->nick, b);
1466                                 // M token for a usermode must go to all servers
1467                                 char buffer[MAXBUF];
1468                                 snprintf(buffer,MAXBUF,"m %s %s %s",user->nick, dest->nick, b);
1469                                 NetSendToAll(buffer);
1470                         }
1471
1472                         if (strlen(dmodes)>MAXMODES)
1473                         {
1474                                 dmodes[MAXMODES-1] = '\0';
1475                         }
1476                         log(DEBUG,"Stripped mode line");
1477                         log(DEBUG,"Line dest is now %s",dmodes);
1478                         strlcpy(dest->modes,dmodes,52);
1479
1480                 }
1481
1482                 return;
1483         }
1484         
1485         Ptr = FindChan(parameters[0]);
1486         if (Ptr)
1487         {
1488                 if (pcnt == 1)
1489                 {
1490                         /* just /modes #channel */
1491                         WriteServ(user->fd,"324 %s %s +%s",user->nick, Ptr->name, chanmodes(Ptr));
1492                         WriteServ(user->fd,"329 %s %s %d", user->nick, Ptr->name, Ptr->created);
1493                         return;
1494                 }
1495                 else
1496                 if (pcnt == 2)
1497                 {
1498                         char* mode = parameters[1];
1499                         if (*mode == '+')
1500                                 mode++;
1501                         int MOD_RESULT = 0;
1502                         FOREACH_RESULT(OnRawMode(user, Ptr, *mode, "", false, 0));
1503                         if (!MOD_RESULT)
1504                         {
1505                                 if (*mode == 'b')
1506                                 {
1507
1508                                         for (BanList::iterator i = Ptr->bans.begin(); i != Ptr->bans.end(); i++)
1509                                         {
1510                                                 WriteServ(user->fd,"367 %s %s %s %s %d",user->nick, Ptr->name, i->data, i->set_by, i->set_time);
1511                                         }
1512                                         WriteServ(user->fd,"368 %s %s :End of channel ban list",user->nick, Ptr->name);
1513                                         return;
1514                                 }
1515                                 if ((ModeDefined(*mode,MT_CHANNEL)) && (ModeIsListMode(*mode,MT_CHANNEL)))
1516                                 {
1517                                         // list of items for an extmode
1518                                         log(DEBUG,"Calling OnSendList for all modules, list output for mode %c",*mode);
1519                                         FOREACH_MOD OnSendList(user,Ptr,*mode);
1520                                         return;
1521                                 }
1522                         }
1523                 }
1524
1525                 if ((Ptr) && (!has_channel(user,Ptr)))
1526                 {
1527                         WriteServ(user->fd,"442 %s %s :You're not on that channel!",user->nick, Ptr->name);
1528                         return;
1529                 }
1530
1531                 if (Ptr)
1532                 {
1533                         int MOD_RESULT = 0;
1534                         FOREACH_RESULT(OnAccessCheck(user,NULL,Ptr,AC_GENERAL_MODE));
1535                         
1536                         if (MOD_RESULT == ACR_DENY)
1537                                 return;
1538                         if (MOD_RESULT == ACR_DEFAULT)
1539                         {
1540                                 if (cstatus(user,Ptr) < STATUS_HOP)
1541                                 {
1542                                         WriteServ(user->fd,"482 %s %s :You must be at least a half-operator to change modes on this channel",user->nick, Ptr->name);
1543                                         return;
1544                                 }
1545                         }
1546
1547                         process_modes(parameters,user,Ptr,cstatus(user,Ptr),pcnt,false,false,false);
1548                 }
1549         }
1550         else
1551         {
1552                 WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, parameters[0]);
1553         }
1554 }
1555
1556
1557
1558
1559 void server_mode(char **parameters, int pcnt, userrec *user)
1560 {
1561         chanrec* Ptr;
1562         userrec* dest;
1563         int can_change;
1564         int direction = 1;
1565         char outpars[MAXBUF];
1566
1567         dest = Find(parameters[0]);
1568         
1569         // fix: ChroNiCk found this - we cant use this as debug if its null!
1570         if (dest)
1571         {
1572                 log(DEBUG,"server_mode on %s",dest->nick);
1573         }
1574
1575         if ((dest) && (pcnt > 1))
1576         {
1577                 std::string tidied = compress_modes(parameters[1],false);
1578                 parameters[1] = (char*)tidied.c_str();
1579
1580                 char dmodes[MAXBUF];
1581                 strlcpy(dmodes,dest->modes,52);
1582
1583                 strcpy(outpars,"+");
1584                 direction = 1;
1585
1586                 if ((parameters[1][0] != '+') && (parameters[1][0] != '-'))
1587                         return;
1588
1589                 for (unsigned int i = 0; i < strlen(parameters[1]); i++)
1590                 {
1591                         if (parameters[1][i] == ' ')
1592                                 continue;
1593                         if (parameters[1][i] == '+')
1594                         {
1595                                 if (direction != 1)
1596                                 {
1597                                         int t = strlen(outpars)-1;
1598                                         if ((outpars[t] == '+') || (outpars[t] == '-'))
1599                                         {
1600                                                 outpars[t] = '+';
1601                                         }
1602                                         else
1603                                         {
1604                                                 strcat(outpars,"+");
1605                                         }
1606                                 }
1607                                 direction = 1;
1608                         }
1609                         else
1610                         if (parameters[1][i] == '-')
1611                         {
1612                                 if (direction != 0)
1613                                 {
1614                                         int t = strlen(outpars)-1;
1615                                         if ((outpars[t] == '+') || (outpars[t] == '-'))
1616                                         {
1617                                                 outpars[t] = '-';
1618                                         }
1619                                         else
1620                                         {
1621                                                 strcat(outpars,"-");
1622                                         }
1623                                 }
1624                                 direction = 0;
1625                         }
1626                         else
1627                         {
1628                                 log(DEBUG,"begin mode processing entry");
1629                                 can_change = 1;
1630                                 if (can_change)
1631                                 {
1632                                         if (direction == 1)
1633                                         {
1634                                                 log(DEBUG,"umode %c being added",parameters[1][i]);
1635                                                 if ((!strchr(dmodes,parameters[1][i])) && (allowed_umode(parameters[1][i],user->modes,true)))
1636                                                 {
1637                                                         char umode = parameters[1][i];
1638                                                         log(DEBUG,"umode %c is an allowed umode",umode);
1639                                                         if ((process_module_umode(umode, user, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
1640                                                         {
1641                                                                 int v1 = strlen(dmodes);
1642                                                                 int v2 = strlen(outpars);
1643                                                                 dmodes[v1+1]='\0';
1644                                                                 dmodes[v1] = parameters[1][i];
1645                                                                 outpars[v2+1]='\0';
1646                                                                 outpars[v2] = parameters[1][i];
1647                                                         }
1648                                                 }
1649                                         }
1650                                         else
1651                                         {
1652                                                 // can only remove a mode they already have
1653                                                 log(DEBUG,"umode %c being removed",parameters[1][i]);
1654                                                 if ((allowed_umode(parameters[1][i],user->modes,false)) && (strchr(dmodes,parameters[1][i])))
1655                                                 {
1656                                                         char umode = parameters[1][i];
1657                                                         log(DEBUG,"umode %c is an allowed umode",umode);
1658                                                         if ((process_module_umode(umode, user, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
1659                                                         {
1660                                                                 unsigned int q = 0;
1661                                                                 char temp[MAXBUF];
1662                                                                 char moo[MAXBUF];       
1663
1664                                                                 unsigned int v1 = strlen(outpars);
1665                                                                 outpars[v1+1]='\0';
1666                                                                 outpars[v1] = parameters[1][i];
1667                                                         
1668                                                                 strcpy(temp,"");
1669                                                                 for (q = 0; q < strlen(dmodes); q++)
1670                                                                 {
1671                                                                         if (dmodes[q] != parameters[1][i])
1672                                                                         {
1673                                                                                 moo[0] = dmodes[q];
1674                                                                                 moo[1] = '\0';
1675                                                                                 strlcat(temp,moo,MAXBUF);
1676                                                                         }
1677                                                                 }
1678                                                                 strlcpy(dmodes,temp,52);
1679                                                         }
1680                                                 }
1681                                         }
1682                                 }
1683                         }
1684                 }
1685                 if (outpars[0])
1686                 {
1687                         char b[MAXBUF];
1688                         strlcpy(b,"",MAXBUF);
1689                         unsigned int z = 0;
1690                         unsigned int i = 0;
1691                         while (i < strlen (outpars))
1692                         {
1693                                 b[z++] = outpars[i++];
1694                                 b[z] = '\0';
1695                                 if (i<strlen(outpars)-1)
1696                                 {
1697                                         if (((outpars[i] == '-') || (outpars[i] == '+')) && ((outpars[i+1] == '-') || (outpars[i+1] == '+')))
1698                                         {
1699                                                 // someones playing silly buggers and trying
1700                                                 // to put a +- or -+ into the line...
1701                                                 i++;
1702                                         }
1703                                 }
1704                                 if (i == strlen(outpars)-1)
1705                                 {
1706                                         if ((outpars[i] == '-') || (outpars[i] == '+'))
1707                                         {
1708                                                 i++;
1709                                         }
1710                                 }
1711                         }
1712
1713                         z = strlen(b)-1;
1714                         if ((b[z] == '-') || (b[z] == '+'))
1715                                 b[z] = '\0';
1716
1717                         if ((!b[0]) || (!strcmp(b,"+")) || (!strcmp(b,"-")))
1718                                 return;
1719
1720                         if (strcmp(b,""))
1721                         {
1722                                 WriteTo(user, dest, "MODE %s :%s", dest->nick, b);
1723                                 // M token for a usermode must go to all servers
1724                                 char buffer[MAXBUF];
1725                                 snprintf(buffer,MAXBUF,"m %s %s %s",user->nick, dest->nick, b);
1726                                 NetSendToAll(buffer);
1727                         }
1728                         
1729                         if (strlen(dmodes)>MAXMODES)
1730                         {
1731                                 dmodes[MAXMODES-1] = '\0';
1732                         }
1733                         log(DEBUG,"Stripped mode line");
1734                         log(DEBUG,"Line dest is now %s",dmodes);
1735                         strlcpy(dest->modes,dmodes,MAXMODES);
1736
1737                 }
1738
1739                 return;
1740         }
1741         
1742         Ptr = FindChan(parameters[0]);
1743         if (Ptr)
1744         {
1745                 process_modes(parameters,user,Ptr,STATUS_OP,pcnt,true,false,false);
1746         }
1747         else
1748         {
1749                 WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, parameters[0]);
1750         }
1751 }
1752
1753
1754
1755 void merge_mode(char **parameters, int pcnt)
1756 {
1757         chanrec* Ptr;
1758         userrec* dest;
1759         int can_change;
1760         int direction = 1;
1761         char outpars[MAXBUF];
1762
1763         dest = Find(parameters[0]);
1764         
1765         // fix: ChroNiCk found this - we cant use this as debug if its null!
1766         if (dest)
1767         {
1768                 log(DEBUG,"merge_mode on %s",dest->nick);
1769         }
1770
1771         if ((dest) && (pcnt > 1))
1772         {
1773                 std::string tidied = compress_modes(parameters[1],false);
1774                 parameters[1] = (char*)tidied.c_str();
1775
1776                 char dmodes[MAXBUF];
1777                 strlcpy(dmodes,dest->modes,52);
1778
1779                 strcpy(outpars,"+");
1780                 direction = 1;
1781
1782                 if ((parameters[1][0] != '+') && (parameters[1][0] != '-'))
1783                         return;
1784
1785                 for (unsigned int i = 0; i < strlen(parameters[1]); i++)
1786                 {
1787                         if (parameters[1][i] == ' ')
1788                                 continue;
1789                         if (parameters[1][i] == '+')
1790                         {
1791                                 if (direction != 1)
1792                                 {
1793                                         int t = strlen(outpars)-1;
1794                                         if ((outpars[t] == '+') || (outpars[t] == '-'))
1795                                         {
1796                                                 outpars[t] = '+';
1797                                         }
1798                                         else
1799                                         {
1800                                                 strcat(outpars,"+");
1801                                         }
1802                                 }
1803                                 direction = 1;
1804                         }
1805                         else
1806                         if (parameters[1][i] == '-')
1807                         {
1808                                 if (direction != 0)
1809                                 {
1810                                         int t = strlen(outpars)-1;
1811                                         if ((outpars[t] == '+') || (outpars[t] == '-'))
1812                                         {
1813                                                 outpars[t] = '-';
1814                                         }
1815                                         else
1816                                         {
1817                                                 strcat(outpars,"-");
1818                                         }
1819                                 }
1820                                 direction = 0;
1821                         }
1822                         else
1823                         {
1824                                 log(DEBUG,"begin mode processing entry");
1825                                 can_change = 1;
1826                                 if (can_change)
1827                                 {
1828                                         if (direction == 1)
1829                                         {
1830                                                 log(DEBUG,"umode %c being added",parameters[1][i]);
1831                                                 if ((!strchr(dmodes,parameters[1][i])) && (allowed_umode(parameters[1][i],"o",true)))
1832                                                 {
1833                                                         char umode = parameters[1][i];
1834                                                         log(DEBUG,"umode %c is an allowed umode",umode);
1835                                                         if ((process_module_umode(umode, NULL, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
1836                                                         {
1837                                                                 int v1 = strlen(dmodes);
1838                                                                 int v2 = strlen(outpars);
1839                                                                 dmodes[v1+1]='\0';
1840                                                                 dmodes[v1] = parameters[1][i];
1841                                                                 outpars[v2+1]='\0';
1842                                                                 outpars[v2] = parameters[1][i];
1843                                                         }
1844                                                 }
1845                                         }
1846                                         else
1847                                         {
1848                                                 // can only remove a mode they already have
1849                                                 log(DEBUG,"umode %c being removed",parameters[1][i]);
1850                                                 if ((allowed_umode(parameters[1][i],"o",false)) && (strchr(dmodes,parameters[1][i])))
1851                                                 {
1852                                                         char umode = parameters[1][i];
1853                                                         log(DEBUG,"umode %c is an allowed umode",umode);
1854                                                         if ((process_module_umode(umode, NULL, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
1855                                                         {
1856                                                                 unsigned int q = 0;
1857                                                                 char temp[MAXBUF];
1858                                                                 char moo[MAXBUF];       
1859
1860                                                                 unsigned int v1 = strlen(outpars);
1861                                                                 outpars[v1+1]='\0';
1862                                                                 outpars[v1] = parameters[1][i];
1863                                                         
1864                                                                 strcpy(temp,"");
1865                                                                 for (q = 0; q < strlen(dmodes); q++)
1866                                                                 {
1867                                                                         if (dmodes[q] != parameters[1][i])
1868                                                                         {
1869                                                                                 moo[0] = dmodes[q];
1870                                                                                 moo[1] = '\0';
1871                                                                                 strlcat(temp,moo,MAXBUF);
1872                                                                         }
1873                                                                 }
1874                                                                 strlcpy(dmodes,temp,52);
1875                                                         }
1876                                                 }
1877                                         }
1878                                 }
1879                         }
1880                 }
1881                 if (outpars[0])
1882                 {
1883                         char b[MAXBUF];
1884                         strcpy(b,"");
1885                         unsigned int z = 0;
1886                         unsigned int i = 0;
1887                         while (i < strlen (outpars))
1888                         {
1889                                 b[z++] = outpars[i++];
1890                                 b[z] = '\0';
1891                                 if (i<strlen(outpars)-1)
1892                                 {
1893                                         if (((outpars[i] == '-') || (outpars[i] == '+')) && ((outpars[i+1] == '-') || (outpars[i+1] == '+')))
1894                                         {
1895                                                 // someones playing silly buggers and trying
1896                                                 // to put a +- or -+ into the line...
1897                                                 i++;
1898                                         }
1899                                 }
1900                                 if (i == strlen(outpars)-1)
1901                                 {
1902                                         if ((outpars[i] == '-') || (outpars[i] == '+'))
1903                                         {
1904                                                 i++;
1905                                         }
1906                                 }
1907                         }
1908
1909                         z = strlen(b)-1;
1910                         if ((b[z] == '-') || (b[z] == '+'))
1911                                 b[z] = '\0';
1912
1913                         if ((!strcmp(b,"+")) || (!strcmp(b,"-")))
1914                                 return;
1915
1916                         if (strlen(dmodes)>MAXMODES)
1917                         {
1918                                 dmodes[MAXMODES-1] = '\0';
1919                         }
1920                         log(DEBUG,"Stripped mode line");
1921                         log(DEBUG,"Line dest is now %s",dmodes);
1922                         strlcpy(dest->modes,dmodes,MAXMODES);
1923
1924                 }
1925
1926                 return;
1927         }
1928         
1929         Ptr = FindChan(parameters[0]);
1930         if (Ptr)
1931         {
1932                 userrec s2;
1933                 strlcpy(s2.nick,ServerName,NICKMAX);
1934                 strcpy(s2.modes,"o");
1935                 s2.fd = -1;
1936                 process_modes(parameters,&s2,Ptr,STATUS_OP,pcnt,true,true,false);
1937         }
1938 }
1939
1940
1941 void merge_mode2(char **parameters, int pcnt, userrec* user)
1942 {
1943         chanrec* Ptr;
1944         userrec* dest;
1945         int can_change;
1946         int direction = 1;
1947         char outpars[MAXBUF];
1948
1949         dest = Find(parameters[0]);
1950         
1951         // fix: ChroNiCk found this - we cant use this as debug if its null!
1952         if (dest)
1953         {
1954                 log(DEBUG,"merge_mode2 on %s",dest->nick);
1955         }
1956
1957         if ((dest) && (pcnt > 1))
1958         {
1959                 std::string tidied = compress_modes(parameters[1],false);
1960                 parameters[1] = (char*)tidied.c_str();
1961
1962                 char dmodes[MAXBUF];
1963                 strlcpy(dmodes,dest->modes,52);
1964
1965                 strcpy(outpars,"+");
1966                 direction = 1;
1967
1968                 if ((parameters[1][0] == ':') && (strlen(parameters[1])>1))
1969                 {
1970                         // some stupid 3rd party things (such as services packages) put a colon on the mode list...
1971                         log(DEBUG,"Some muppet put a colon on the modelist! changed to '%s'",++parameters[1]);
1972                 }
1973                 if ((parameters[1][0] != '+') && (parameters[1][0] != '-'))
1974                 return;
1975
1976                 for (unsigned int i = 0; i < strlen(parameters[1]); i++)
1977                 {
1978                         if (parameters[1][i] == ' ')
1979                                 continue;
1980                         if (parameters[1][i] == '+')
1981                         {
1982                                 if (direction != 1)
1983                                 {
1984                                         int t = strlen(outpars)-1;
1985                                         if ((outpars[t] == '+') || (outpars[t] == '-'))
1986                                         {
1987                                                 outpars[t] = '+';
1988                                         }
1989                                         else
1990                                         {
1991                                                 strcat(outpars,"+");
1992                                         }
1993                                 }
1994                                 direction = 1;
1995                         }
1996                         else
1997                         if (parameters[1][i] == '-')
1998                         {
1999                                 if (direction != 0)
2000                                 {
2001                                         int t = strlen(outpars)-1;
2002                                         if ((outpars[t] == '+') || (outpars[t] == '-'))
2003                                         {
2004                                                 outpars[t] = '-';
2005                                         }
2006                                         else
2007                                         {
2008                                                 strcat(outpars,"-");
2009                                         }
2010                                 }
2011                                 direction = 0;
2012                         }
2013                         else
2014                         {
2015                                 log(DEBUG,"begin mode processing entry");
2016                                 can_change = 1;
2017                                 if (can_change)
2018                                 {
2019                                         if (direction == 1)
2020                                         {
2021                                                 log(DEBUG,"umode %c being added",parameters[1][i]);
2022                                                 if ((!strchr(dmodes,parameters[1][i])) && (allowed_umode(parameters[1][i],user->modes,true)))
2023                                                 {
2024                                                         char umode = parameters[1][i];
2025                                                         log(DEBUG,"umode %c is an allowed umode",umode);
2026                                                         if ((process_module_umode(umode, NULL, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
2027                                                         {
2028                                                                 int v1 = strlen(dmodes);
2029                                                                 int v2 = strlen(outpars);
2030                                                                 dmodes[v1+1]='\0';
2031                                                                 dmodes[v1] = parameters[1][i];
2032                                                                 outpars[v2+1]='\0';
2033                                                                 outpars[v2] = parameters[1][i];
2034                                                                 log(DEBUG,"OUTPARS='%s', DMODES='%s'",outpars,dmodes);
2035                                                         }
2036                                                 }
2037                                         }
2038                                         else
2039                                         {
2040                                                 // can only remove a mode they already have
2041                                                 log(DEBUG,"umode %c being removed",parameters[1][i]);
2042                                                 if ((allowed_umode(parameters[1][i],user->modes,false)) && (strchr(dmodes,parameters[1][i])))
2043                                                 {
2044                                                         char umode = parameters[1][i];
2045                                                         log(DEBUG,"umode %c is an allowed umode",umode);
2046                                                         if ((process_module_umode(umode, NULL, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
2047                                                         {
2048                                                                 unsigned int q = 0;
2049                                                                 char temp[MAXBUF];
2050                                                                 char moo[MAXBUF];       
2051
2052                                                                 unsigned int v1 = strlen(outpars);
2053                                                                 outpars[v1+1]='\0';
2054                                                                 outpars[v1] = parameters[1][i];
2055                                                         
2056                                                                 strcpy(temp,"");
2057                                                                 for (q = 0; q < strlen(dmodes); q++)
2058                                                                 {
2059                                                                         if (dmodes[q] != parameters[1][i])
2060                                                                         {
2061                                                                                 moo[0] = dmodes[q];
2062                                                                                 moo[1] = '\0';
2063                                                                                 strlcat(temp,moo,MAXBUF);
2064                                                                         }
2065                                                                 }
2066                                                                 strlcpy(dmodes,temp,52);
2067                                                         }
2068                                                 }
2069                                         }
2070                                 }
2071                         }
2072                 }
2073                 log(DEBUG,"DONE! OUTPARS='%s', DMODES='%s'",outpars,dmodes);
2074                 if (outpars[0])
2075                 {
2076                         char b[MAXBUF];
2077                         strcpy(b,"");
2078                         unsigned int z = 0;
2079                         unsigned int i = 0;
2080                         while (i < strlen (outpars))
2081                         {
2082                                 b[z++] = outpars[i++];
2083                                 b[z] = '\0';
2084                                 if (i<strlen(outpars)-1)
2085                                 {
2086                                         if (((outpars[i] == '-') || (outpars[i] == '+')) && ((outpars[i+1] == '-') || (outpars[i+1] == '+')))
2087                                         {
2088                                                 // someones playing silly buggers and trying
2089                                                 // to put a +- or -+ into the line...
2090                                                 i++;
2091                                         }
2092                                 }
2093                                 if (i == strlen(outpars)-1)
2094                                 {
2095                                         if ((outpars[i] == '-') || (outpars[i] == '+'))
2096                                         {
2097                                                 i++;
2098                                         }
2099                                 }
2100                         }
2101
2102                         z = strlen(b)-1;
2103                         if ((b[z] == '-') || (b[z] == '+'))
2104                                 b[z] = '\0';
2105
2106
2107                         if ((!b[0]) || (!strcmp(b,"+")) || (!strcmp(b,"-")))
2108                                 return;
2109
2110                         if (strcmp(b,""))
2111                         {
2112                                 WriteTo(user,dest,"MODE %s :%s",dest->nick,b);
2113                                 log(DEBUG,"Sent: :%s MODE %s",user->nick,b);
2114                         }
2115
2116                         if (strlen(dmodes)>MAXMODES)
2117                         {
2118                                 dmodes[MAXMODES-1] = '\0';
2119                         }
2120                         log(DEBUG,"Stripped mode line");
2121                         log(DEBUG,"Line dest is now %s",dmodes);
2122                         strlcpy(dest->modes,dmodes,MAXMODES);
2123                 }
2124
2125                 return;
2126         }
2127         
2128         Ptr = FindChan(parameters[0]);
2129         if (Ptr)
2130         {
2131                 log(DEBUG,"merge_mode2: found channel %s",Ptr->name);
2132                 if (Ptr)
2133                 {
2134                         if ((cstatus(user,Ptr) < STATUS_HOP) && (!is_uline(user->server)))
2135                         {
2136                                 return;
2137                         }
2138                         process_modes(parameters,user,Ptr,cstatus(user,Ptr),pcnt,false,false,true);
2139                 }
2140         }
2141 }
2142
2143