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