2 #include "inspircd_io.h"
3 #include "inspircd_util.h"
4 #include "inspircd_config.h"
9 #include <sys/utsname.h>
14 #include <ext/hash_map>
26 #include "connection.h"
41 extern vector<Module*> modules;
42 extern vector<ircd_module*> factory;
43 extern std::vector<std::string> module_names;
47 extern char ServerName[MAXBUF];
48 extern char Network[MAXBUF];
49 extern char ServerDesc[MAXBUF];
50 extern char AdminName[MAXBUF];
51 extern char AdminEmail[MAXBUF];
52 extern char AdminNick[MAXBUF];
53 extern char diepass[MAXBUF];
54 extern char restartpass[MAXBUF];
55 extern char motd[MAXBUF];
56 extern char rules[MAXBUF];
57 extern char list[MAXBUF];
58 extern char PrefixQuit[MAXBUF];
59 extern char DieValue[MAXBUF];
61 extern bool AllowHalfop;
62 extern bool AllowProtect;
63 extern bool AllowFounder;
66 char* give_ops(userrec *user,char *dest,chanrec *chan,int status)
71 if ((!user) || (!dest) || (!chan))
73 log(DEFAULT,"*** BUG *** give_ops was given an invalid parameter");
79 log(DEFAULT,"the target nickname given to give_ops was invalid");
80 WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest);
86 log(DEFAULT,"the target nickname given to give_ops couldnt be found");
87 WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest);
94 FOREACH_RESULT(OnAccessCheck(user,d,chan,AC_OP));
96 if (MOD_RESULT == ACR_DENY)
98 if (MOD_RESULT == ACR_DEFAULT)
100 if ((status < STATUS_OP) && (!is_uline(user->server)))
102 log(DEBUG,"%s cant give ops to %s because they nave status %d and needs %d",user->nick,dest,status,STATUS_OP);
103 WriteServ(user->fd,"482 %s %s :You're not a channel operator",user->nick, chan->name);
109 for (int i = 0; i != MAXCHANS; i++)
111 if ((d->chans[i].channel != NULL) && (chan != NULL))
112 if (!strcasecmp(d->chans[i].channel->name,chan->name))
114 if (d->chans[i].uc_modes & UCMODE_OP)
116 /* mode already set on user, dont allow multiple */
117 log(DEFAULT,"The target user given to give_ops was already opped on the channel");
120 d->chans[i].uc_modes = d->chans[i].uc_modes | UCMODE_OP;
121 log(DEBUG,"gave ops: %s %s",d->chans[i].channel->name,d->nick);
125 log(DEFAULT,"The target channel given to give_ops was not in the users mode list");
130 char* give_hops(userrec *user,char *dest,chanrec *chan,int status)
135 if ((!user) || (!dest) || (!chan))
137 log(DEFAULT,"*** BUG *** give_hops was given an invalid parameter");
144 WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest);
149 WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest);
155 FOREACH_RESULT(OnAccessCheck(user,d,chan,AC_HALFOP));
157 if (MOD_RESULT == ACR_DENY)
159 if (MOD_RESULT == ACR_DEFAULT)
161 if ((status < STATUS_OP) && (!is_uline(user->server)))
163 WriteServ(user->fd,"482 %s %s :You're not a channel operator",user->nick, chan->name);
168 for (int i = 0; i != MAXCHANS; i++)
170 if ((d->chans[i].channel != NULL) && (chan != NULL))
171 if (!strcasecmp(d->chans[i].channel->name,chan->name))
173 if (d->chans[i].uc_modes & UCMODE_HOP)
175 /* mode already set on user, dont allow multiple */
178 d->chans[i].uc_modes = d->chans[i].uc_modes | UCMODE_HOP;
179 log(DEBUG,"gave h-ops: %s %s",d->chans[i].channel->name,d->nick);
187 char* give_voice(userrec *user,char *dest,chanrec *chan,int status)
192 if ((!user) || (!dest) || (!chan))
194 log(DEFAULT,"*** BUG *** give_voice was given an invalid parameter");
201 WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest);
206 WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest);
212 FOREACH_RESULT(OnAccessCheck(user,d,chan,AC_VOICE));
214 if (MOD_RESULT == ACR_DENY)
216 if (MOD_RESULT == ACR_DEFAULT)
218 if ((status < STATUS_HOP) && (!is_uline(user->server)))
220 WriteServ(user->fd,"482 %s %s :You must be at least a half-operator to change modes on this channel",user->nick, chan->name);
225 for (int i = 0; i != MAXCHANS; i++)
227 if ((d->chans[i].channel != NULL) && (chan != NULL))
228 if (!strcasecmp(d->chans[i].channel->name,chan->name))
230 if (d->chans[i].uc_modes & UCMODE_VOICE)
232 /* mode already set on user, dont allow multiple */
235 d->chans[i].uc_modes = d->chans[i].uc_modes | UCMODE_VOICE;
236 log(DEBUG,"gave voice: %s %s",d->chans[i].channel->name,d->nick);
244 char* take_ops(userrec *user,char *dest,chanrec *chan,int status)
249 if ((!user) || (!dest) || (!chan))
251 log(DEFAULT,"*** BUG *** take_ops was given an invalid parameter");
258 log(DEBUG,"take_ops was given an invalid target nickname of %s",dest);
259 WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest);
264 log(DEBUG,"take_ops couldnt resolve the target nickname: %s",dest);
265 WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest);
271 FOREACH_RESULT(OnAccessCheck(user,d,chan,AC_DEOP));
273 if (MOD_RESULT == ACR_DENY)
275 if (MOD_RESULT == ACR_DEFAULT)
277 if ((status < STATUS_OP) && (!is_uline(user->server)))
279 WriteServ(user->fd,"482 %s %s :You are not a channel operator",user->nick, chan->name);
284 for (int i = 0; i != MAXCHANS; i++)
286 if ((d->chans[i].channel != NULL) && (chan != NULL))
287 if (!strcasecmp(d->chans[i].channel->name,chan->name))
289 if ((d->chans[i].uc_modes & UCMODE_OP) == 0)
291 /* mode already set on user, dont allow multiple */
294 d->chans[i].uc_modes ^= UCMODE_OP;
295 log(DEBUG,"took ops: %s %s",d->chans[i].channel->name,d->nick);
299 log(DEBUG,"take_ops couldnt locate the target channel in the target users list");
304 char* take_hops(userrec *user,char *dest,chanrec *chan,int status)
309 if ((!user) || (!dest) || (!chan))
311 log(DEFAULT,"*** BUG *** take_hops was given an invalid parameter");
318 WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest);
323 WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest);
329 FOREACH_RESULT(OnAccessCheck(user,d,chan,AC_DEHALFOP));
331 if (MOD_RESULT == ACR_DENY)
333 if (MOD_RESULT == ACR_DEFAULT)
335 if ((status < STATUS_OP) && (!is_uline(user->server)))
337 WriteServ(user->fd,"482 %s %s :You are not a channel operator",user->nick, chan->name);
342 for (int i = 0; i != MAXCHANS; i++)
344 if ((d->chans[i].channel != NULL) && (chan != NULL))
345 if (!strcasecmp(d->chans[i].channel->name,chan->name))
347 if ((d->chans[i].uc_modes & UCMODE_HOP) == 0)
349 /* mode already set on user, dont allow multiple */
352 d->chans[i].uc_modes ^= UCMODE_HOP;
353 log(DEBUG,"took h-ops: %s %s",d->chans[i].channel->name,d->nick);
361 char* take_voice(userrec *user,char *dest,chanrec *chan,int status)
366 if ((!user) || (!dest) || (!chan))
368 log(DEFAULT,"*** BUG *** take_voice was given an invalid parameter");
375 WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest);
380 WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest);
386 FOREACH_RESULT(OnAccessCheck(user,d,chan,AC_DEVOICE));
388 if (MOD_RESULT == ACR_DENY)
390 if (MOD_RESULT == ACR_DEFAULT)
392 if ((status < STATUS_HOP) && (!is_uline(user->server)))
394 WriteServ(user->fd,"482 %s %s :You must be at least a half-operator to change modes on this channel",user->nick, chan->name);
399 for (int i = 0; i != MAXCHANS; i++)
401 if ((d->chans[i].channel != NULL) && (chan != NULL))
402 if (!strcasecmp(d->chans[i].channel->name,chan->name))
404 if ((d->chans[i].uc_modes & UCMODE_VOICE) == 0)
406 /* mode already set on user, dont allow multiple */
409 d->chans[i].uc_modes ^= UCMODE_VOICE;
410 log(DEBUG,"took voice: %s %s",d->chans[i].channel->name,d->nick);
418 char* add_ban(userrec *user,char *dest,chanrec *chan,int status)
420 if ((!user) || (!dest) || (!chan)) {
421 log(DEFAULT,"*** BUG *** add_ban was given an invalid parameter");
426 if ((!user) || (!dest) || (!chan))
428 if (strchr(dest,'!')==0)
430 if (strchr(dest,'@')==0)
432 for (int i = 0; i < strlen(dest); i++)
435 for (int i = 0; i < strlen(dest); i++)
439 for (int i = 0; i < strlen(dest); i++)
445 for (int i = 0; i < strlen(dest); i++)
450 log(DEBUG,"add_ban: %s %s",chan->name,user->nick);
453 for (BanList::iterator i = chan->bans.begin(); i != chan->bans.end(); i++)
455 if (!strcasecmp(i->data,dest))
457 // dont allow a user to set the same ban twice
462 b.set_time = time(NULL);
463 strncpy(b.data,dest,MAXBUF);
464 strncpy(b.set_by,user->nick,NICKMAX);
465 chan->bans.push_back(b);
469 char* take_ban(userrec *user,char *dest,chanrec *chan,int status)
471 if ((!user) || (!dest) || (!chan)) {
472 log(DEFAULT,"*** BUG *** take_ban was given an invalid parameter");
476 log(DEBUG,"del_ban: %s %s",chan->name,user->nick);
477 for (BanList::iterator i = chan->bans.begin(); i != chan->bans.end(); i++)
479 if (!strcasecmp(i->data,dest))
488 void process_modes(char **parameters,userrec* user,chanrec *chan,int status, int pcnt, bool servermode, bool silent, bool local)
491 log(DEFAULT,"*** BUG *** process_modes was given an invalid parameter");
495 char modelist[MAXBUF];
496 char outlist[MAXBUF];
498 char outpars[32][MAXBUF];
504 bool k_set = false, l_set = false;
512 FOREACH_RESULT(OnAccessCheck(user,NULL,chan,AC_GENERAL_MODE));
514 if (MOD_RESULT == ACR_DENY)
517 log(DEBUG,"process_modes: start: parameters=%d",pcnt);
519 strcpy(modelist,parameters[1]); /* mode list, e.g. +oo-o */
520 /* parameters[2] onwards are parameters for
521 * modes that require them :) */
525 log(DEBUG,"process_modes: modelist: %s",modelist);
527 for (ptr = 0; ptr < strlen(modelist); ptr++)
532 log(DEBUG,"process_modes: modechar: %c",modelist[ptr]);
533 char modechar = modelist[ptr];
534 switch (modelist[ptr])
539 if ((outlist[strlen(outlist)-1] == '+') || (outlist[strlen(outlist)-1] == '-'))
541 outlist[strlen(outlist)-1] = '-';
555 if ((outlist[strlen(outlist)-1] == '+') || (outlist[strlen(outlist)-1] == '-'))
557 outlist[strlen(outlist)-1] = '+';
569 if ((param >= pcnt)) break;
570 log(DEBUG,"Enough parameters left");
573 log(DEBUG,"calling give_ops");
574 r = give_ops(user,parameters[param++],chan,status);
578 log(DEBUG,"calling take_ops");
579 r = take_ops(user,parameters[param++],chan,status);
584 strcpy(outpars[pc++],r);
589 if (((param >= pcnt)) || (!AllowHalfop)) break;
592 r = give_hops(user,parameters[param++],chan,status);
596 r = take_hops(user,parameters[param++],chan,status);
601 strcpy(outpars[pc++],r);
607 if ((param >= pcnt)) break;
610 r = give_voice(user,parameters[param++],chan,status);
614 r = take_voice(user,parameters[param++],chan,status);
619 strcpy(outpars[pc++],r);
624 if ((param >= pcnt)) break;
627 r = add_ban(user,parameters[param++],chan,status);
631 r = take_ban(user,parameters[param++],chan,status);
636 strcpy(outpars[pc++],parameters[param-1]);
650 if (!strcmp(chan->key,""))
654 strcpy(key,parameters[param++]);
655 if (strlen(key)>32) {
658 strcpy(outpars[pc++],key);
659 strcpy(chan->key,key);
665 /* checks on -k are case sensitive and only accurate to the
666 first 32 characters */
668 strcpy(key,parameters[param++]);
669 if (strlen(key)>32) {
672 /* only allow -k if correct key given */
673 if (!strcmp(chan->key,key))
676 strcpy(chan->key,"");
677 strcpy(outpars[pc++],key);
692 if ((param >= pcnt)) break;
698 bool invalid = false;
699 for (int i = 0; i < strlen(parameters[param]); i++)
701 if ((parameters[param][i] < '0') || (parameters[param][i] > '9'))
706 if (atoi(parameters[param]) < 1)
714 chan->limit = atoi(parameters[param]);
716 // reported by mech: large values cause underflow
718 chan->limit = 0x7FFFFF;
723 strcpy(outpars[pc++],parameters[param++]);
730 if (chan->inviteonly != mdir)
734 chan->inviteonly = mdir;
738 if (chan->topiclock != mdir)
742 chan->topiclock = mdir;
746 if (chan->noexternal != mdir)
750 chan->noexternal = mdir;
754 if (chan->moderated != mdir)
758 chan->moderated = mdir;
762 if (chan->secret != mdir)
770 strcat(outlist,"-p+");
774 strcat(outlist,"+p-");
782 if (chan->c_private != mdir)
790 strcat(outlist,"-s+");
794 strcat(outlist,"+s-");
798 chan->c_private = mdir;
802 log(DEBUG,"Preprocessing custom mode %c",modechar);
805 if (((!strchr(chan->custom_modes,modechar)) && (!mdir)) || ((strchr(chan->custom_modes,modechar)) && (mdir)))
807 if (!ModeIsListMode(modechar,MT_CHANNEL))
809 log(DEBUG,"Mode %c isnt set on %s but trying to remove!",modechar,chan->name);
813 if (ModeDefined(modechar,MT_CHANNEL))
815 log(DEBUG,"A module has claimed this mode");
818 if ((ModeDefinedOn(modechar,MT_CHANNEL)>0) && (mdir))
820 p.push_back(parameters[param]);
822 if ((ModeDefinedOff(modechar,MT_CHANNEL)>0) && (!mdir))
824 p.push_back(parameters[param]);
827 bool handled = false;
830 log(DEBUG,"Not enough parameters for module-mode %c",modechar);
831 // we're supposed to have a parameter, but none was given... so dont handle the mode.
832 if (((ModeDefinedOn(modechar,MT_CHANNEL)>0) && (mdir)) || ((ModeDefinedOff(modechar,MT_CHANNEL)>0) && (!mdir)))
838 for (int i = 0; i <= MODCOUNT; i++)
842 int t = modules[i]->OnExtendedMode(user,chan,modechar,MT_CHANNEL,mdir,p);
845 log(DEBUG,"OnExtendedMode returned nonzero for a module");
846 char app[] = {modechar, 0};
847 if (ModeIsListMode(modechar,MT_CHANNEL))
857 strcat(outlist, app);
859 strcpy(outpars[pc++],parameters[param++]);
866 if ((modelist[ptr-1] == '+') || (modelist[ptr-1] == '-'))
868 strcat(outlist, app);
870 else if (!strchr(outlist,modechar))
872 strcat(outlist, app);
875 chan->SetCustomMode(modechar,mdir);
876 // include parameters in output if mode has them
877 if ((ModeDefinedOn(modechar,MT_CHANNEL)>0) && (mdir))
879 chan->SetCustomModeParam(modelist[ptr],parameters[param],mdir);
880 strcpy(outpars[pc++],parameters[param++]);
883 // break, because only one module can handle the mode.
895 /* this ensures only the *valid* modes are sent out onto the network */
896 while ((outlist[strlen(outlist)-1] == '-') || (outlist[strlen(outlist)-1] == '+'))
898 outlist[strlen(outlist)-1] = '\0';
900 if (strcmp(outlist,""))
902 strcpy(outstr,outlist);
903 for (ptr = 0; ptr < pc; ptr++)
906 strcat(outstr,outpars[ptr]);
910 log(DEBUG,"Local mode change");
911 WriteChannelLocal(chan, user, "MODE %s %s",chan->name,outstr);
919 WriteChannelWithServ(ServerName,chan,user,"MODE %s %s",chan->name,outstr);
920 // M token for a usermode must go to all servers
922 snprintf(buffer,MAXBUF,"M %s %s",chan->name, outstr);
923 NetSendToAll(buffer);
931 WriteChannel(chan,user,"MODE %s %s",chan->name,outstr);
932 // M token for a usermode must go to all servers
934 snprintf(buffer,MAXBUF,"m %s %s %s",user->nick,chan->name, outstr);
935 NetSendToAll(buffer);
942 // based on sourcemodes, return true or false to determine if umode is a valid mode a user may set on themselves or others.
944 bool allowed_umode(char umode, char* sourcemodes,bool adding)
946 log(DEBUG,"Allowed_umode: %c %s",umode,sourcemodes);
947 // RFC1459 specified modes
948 if ((umode == 'w') || (umode == 's') || (umode == 'i'))
950 log(DEBUG,"umode %c allowed by RFC1459 scemantics",umode);
954 // user may not +o themselves or others, but an oper may de-oper other opers or themselves
955 if ((strchr(sourcemodes,'o')) && (!adding))
957 log(DEBUG,"umode %c allowed by RFC1459 scemantics",umode);
960 else if (umode == 'o')
962 log(DEBUG,"umode %c allowed by RFC1459 scemantics",umode);
966 // process any module-defined modes that need oper
967 if ((ModeDefinedOper(umode,MT_CLIENT)) && (strchr(sourcemodes,'o')))
969 log(DEBUG,"umode %c allowed by module handler (oper only mode)",umode);
973 if (ModeDefined(umode,MT_CLIENT))
975 // process any module-defined modes that don't need oper
976 log(DEBUG,"umode %c allowed by module handler (non-oper mode)",umode);
977 if ((ModeDefinedOper(umode,MT_CLIENT)) && (!strchr(sourcemodes,'o')))
979 // no, this mode needs oper, and this user 'aint got what it takes!
985 // anything else - return false.
986 log(DEBUG,"umode %c not known by any ruleset",umode);
990 bool process_module_umode(char umode, userrec* source, void* dest, bool adding)
997 strncpy(s2->nick,ServerName,NICKMAX);
998 strcpy(s2->modes,"o");
1005 if (ModeDefined(umode,MT_CLIENT))
1007 for (int i = 0; i <= MODCOUNT; i++)
1009 if (modules[i]->OnExtendedMode(source,(void*)dest,umode,MT_CLIENT,adding,p))
1011 log(DEBUG,"Module %s claims umode %c",module_names[i].c_str(),umode);
1015 log(DEBUG,"No module claims umode %c",umode);
1034 void handle_mode(char **parameters, int pcnt, userrec *user)
1040 char outpars[MAXBUF];
1042 dest = Find(parameters[0]);
1049 if ((dest) && (pcnt == 1))
1051 WriteServ(user->fd,"221 %s :+%s",dest->nick,dest->modes);
1055 if ((dest) && (pcnt > 1))
1057 char dmodes[MAXBUF];
1058 strncpy(dmodes,dest->modes,MAXBUF);
1059 log(DEBUG,"pulled up dest user modes: %s",dmodes);
1064 if (strchr(user->modes,'o'))
1075 WriteServ(user->fd,"482 %s :Can't change mode for other users",user->nick);
1079 strcpy(outpars,"+");
1082 if ((parameters[1][0] != '+') && (parameters[1][0] != '-'))
1085 for (int i = 0; i < strlen(parameters[1]); i++)
1087 if (parameters[1][i] == '+')
1091 if ((outpars[strlen(outpars)-1] == '+') || (outpars[strlen(outpars)-1] == '-'))
1093 outpars[strlen(outpars)-1] = '+';
1097 strcat(outpars,"+");
1103 if (parameters[1][i] == '-')
1107 if ((outpars[strlen(outpars)-1] == '+') || (outpars[strlen(outpars)-1] == '-'))
1109 outpars[strlen(outpars)-1] = '-';
1113 strcat(outpars,"-");
1121 if (strchr(user->modes,'o'))
1127 if ((parameters[1][i] == 'i') || (parameters[1][i] == 'w') || (parameters[1][i] == 's') || (allowed_umode(parameters[1][i],user->modes,direction)))
1136 if ((!strchr(dmodes,parameters[1][i])) && (allowed_umode(parameters[1][i],user->modes,true)))
1138 char umode = parameters[1][i];
1139 if ((process_module_umode(umode, user, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
1141 dmodes[strlen(dmodes)+1]='\0';
1142 dmodes[strlen(dmodes)] = parameters[1][i];
1143 outpars[strlen(outpars)+1]='\0';
1144 outpars[strlen(outpars)] = parameters[1][i];
1150 if ((allowed_umode(parameters[1][i],user->modes,false)) && (strchr(dmodes,parameters[1][i])))
1152 char umode = parameters[1][i];
1153 if ((process_module_umode(umode, user, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
1159 outpars[strlen(outpars)+1]='\0';
1160 outpars[strlen(outpars)] = parameters[1][i];
1163 for (q = 0; q < strlen(dmodes); q++)
1165 if (dmodes[q] != parameters[1][i])
1172 strcpy(dmodes,temp);
1179 if (strlen(outpars))
1185 while (i < strlen (outpars))
1187 b[z++] = outpars[i++];
1189 if (i<strlen(outpars)-1)
1191 if (((outpars[i] == '-') || (outpars[i] == '+')) && ((outpars[i+1] == '-') || (outpars[i+1] == '+')))
1193 // someones playing silly buggers and trying
1194 // to put a +- or -+ into the line...
1198 if (i == strlen(outpars)-1)
1200 if ((outpars[i] == '-') || (outpars[i] == '+'))
1208 if ((b[z] == '-') || (b[z] == '+'))
1211 if ((!strcmp(b,"+")) || (!strcmp(b,"-")))
1214 WriteTo(user, dest, "MODE %s :%s", dest->nick, b);
1216 // M token for a usermode must go to all servers
1217 char buffer[MAXBUF];
1218 snprintf(buffer,MAXBUF,"m %s %s %s",user->nick, dest->nick, b);
1219 NetSendToAll(buffer);
1221 if (strlen(dmodes)>MAXMODES)
1223 dmodes[MAXMODES-1] = '\0';
1225 log(DEBUG,"Stripped mode line");
1226 log(DEBUG,"Line dest is now %s",dmodes);
1227 strncpy(dest->modes,dmodes,MAXMODES);
1234 Ptr = FindChan(parameters[0]);
1239 /* just /modes #channel */
1240 WriteServ(user->fd,"324 %s %s +%s",user->nick, Ptr->name, chanmodes(Ptr));
1241 WriteServ(user->fd,"329 %s %s %d", user->nick, Ptr->name, Ptr->created);
1247 if ((!strcmp(parameters[1],"+b")) || (!strcmp(parameters[1],"b")))
1250 for (BanList::iterator i = Ptr->bans.begin(); i != Ptr->bans.end(); i++)
1252 WriteServ(user->fd,"367 %s %s %s %s %d",user->nick, Ptr->name, i->data, i->set_by, i->set_time);
1254 WriteServ(user->fd,"368 %s %s :End of channel ban list",user->nick, Ptr->name);
1260 FOREACH_RESULT(OnAccessCheck(user,NULL,Ptr,AC_GENERAL_MODE));
1262 if (MOD_RESULT == ACR_DENY)
1264 if (MOD_RESULT == ACR_DEFAULT)
1266 if ((cstatus(user,Ptr) < STATUS_HOP) && (Ptr))
1268 WriteServ(user->fd,"482 %s %s :You must be at least a half-operator to change modes on this channel",user->nick, Ptr->name);
1273 process_modes(parameters,user,Ptr,cstatus(user,Ptr),pcnt,false,false,false);
1277 WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, parameters[0]);
1284 void server_mode(char **parameters, int pcnt, userrec *user)
1290 char outpars[MAXBUF];
1292 dest = Find(parameters[0]);
1294 // fix: ChroNiCk found this - we cant use this as debug if its null!
1297 log(DEBUG,"server_mode on %s",dest->nick);
1300 if ((dest) && (pcnt > 1))
1302 log(DEBUG,"params > 1");
1304 char dmodes[MAXBUF];
1305 strncpy(dmodes,dest->modes,MAXBUF);
1307 strcpy(outpars,"+");
1310 if ((parameters[1][0] != '+') && (parameters[1][0] != '-'))
1313 for (int i = 0; i < strlen(parameters[1]); i++)
1315 if (parameters[1][i] == '+')
1319 if ((outpars[strlen(outpars)-1] == '+') || (outpars[strlen(outpars)-1] == '-'))
1321 outpars[strlen(outpars)-1] = '+';
1325 strcat(outpars,"+");
1331 if (parameters[1][i] == '-')
1335 if ((outpars[strlen(outpars)-1] == '+') || (outpars[strlen(outpars)-1] == '-'))
1337 outpars[strlen(outpars)-1] = '-';
1341 strcat(outpars,"-");
1348 log(DEBUG,"begin mode processing entry");
1354 log(DEBUG,"umode %c being added",parameters[1][i]);
1355 if ((!strchr(dmodes,parameters[1][i])) && (allowed_umode(parameters[1][i],user->modes,true)))
1357 char umode = parameters[1][i];
1358 log(DEBUG,"umode %c is an allowed umode",umode);
1359 if ((process_module_umode(umode, user, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
1361 dmodes[strlen(dmodes)+1]='\0';
1362 dmodes[strlen(dmodes)] = parameters[1][i];
1363 outpars[strlen(outpars)+1]='\0';
1364 outpars[strlen(outpars)] = parameters[1][i];
1370 // can only remove a mode they already have
1371 log(DEBUG,"umode %c being removed",parameters[1][i]);
1372 if ((allowed_umode(parameters[1][i],user->modes,false)) && (strchr(dmodes,parameters[1][i])))
1374 char umode = parameters[1][i];
1375 log(DEBUG,"umode %c is an allowed umode",umode);
1376 if ((process_module_umode(umode, user, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
1382 outpars[strlen(outpars)+1]='\0';
1383 outpars[strlen(outpars)] = parameters[1][i];
1386 for (q = 0; q < strlen(dmodes); q++)
1388 if (dmodes[q] != parameters[1][i])
1395 strcpy(dmodes,temp);
1402 if (strlen(outpars))
1408 while (i < strlen (outpars))
1410 b[z++] = outpars[i++];
1412 if (i<strlen(outpars)-1)
1414 if (((outpars[i] == '-') || (outpars[i] == '+')) && ((outpars[i+1] == '-') || (outpars[i+1] == '+')))
1416 // someones playing silly buggers and trying
1417 // to put a +- or -+ into the line...
1421 if (i == strlen(outpars)-1)
1423 if ((outpars[i] == '-') || (outpars[i] == '+'))
1431 if ((b[z] == '-') || (b[z] == '+'))
1434 if ((!strcmp(b,"+")) || (!strcmp(b,"-")))
1437 WriteTo(user, dest, "MODE %s :%s", dest->nick, b);
1439 // M token for a usermode must go to all servers
1440 char buffer[MAXBUF];
1441 snprintf(buffer,MAXBUF,"m %s %s %s",user->nick, dest->nick, b);
1442 NetSendToAll(buffer);
1444 if (strlen(dmodes)>MAXMODES)
1446 dmodes[MAXMODES-1] = '\0';
1448 log(DEBUG,"Stripped mode line");
1449 log(DEBUG,"Line dest is now %s",dmodes);
1450 strncpy(dest->modes,dmodes,MAXMODES);
1457 Ptr = FindChan(parameters[0]);
1460 process_modes(parameters,user,Ptr,STATUS_OP,pcnt,true,false,false);
1464 WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, parameters[0]);
1470 void merge_mode(char **parameters, int pcnt)
1476 char outpars[MAXBUF];
1478 dest = Find(parameters[0]);
1480 // fix: ChroNiCk found this - we cant use this as debug if its null!
1483 log(DEBUG,"merge_mode on %s",dest->nick);
1486 if ((dest) && (pcnt > 1))
1488 log(DEBUG,"params > 1");
1490 char dmodes[MAXBUF];
1491 strncpy(dmodes,dest->modes,MAXBUF);
1493 strcpy(outpars,"+");
1496 if ((parameters[1][0] != '+') && (parameters[1][0] != '-'))
1499 for (int i = 0; i < strlen(parameters[1]); i++)
1501 if (parameters[1][i] == '+')
1505 if ((outpars[strlen(outpars)-1] == '+') || (outpars[strlen(outpars)-1] == '-'))
1507 outpars[strlen(outpars)-1] = '+';
1511 strcat(outpars,"+");
1517 if (parameters[1][i] == '-')
1521 if ((outpars[strlen(outpars)-1] == '+') || (outpars[strlen(outpars)-1] == '-'))
1523 outpars[strlen(outpars)-1] = '-';
1527 strcat(outpars,"-");
1534 log(DEBUG,"begin mode processing entry");
1540 log(DEBUG,"umode %c being added",parameters[1][i]);
1541 if ((!strchr(dmodes,parameters[1][i])) && (allowed_umode(parameters[1][i],"o",true)))
1543 char umode = parameters[1][i];
1544 log(DEBUG,"umode %c is an allowed umode",umode);
1545 if ((process_module_umode(umode, NULL, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
1547 dmodes[strlen(dmodes)+1]='\0';
1548 dmodes[strlen(dmodes)] = parameters[1][i];
1549 outpars[strlen(outpars)+1]='\0';
1550 outpars[strlen(outpars)] = parameters[1][i];
1556 // can only remove a mode they already have
1557 log(DEBUG,"umode %c being removed",parameters[1][i]);
1558 if ((allowed_umode(parameters[1][i],"o",false)) && (strchr(dmodes,parameters[1][i])))
1560 char umode = parameters[1][i];
1561 log(DEBUG,"umode %c is an allowed umode",umode);
1562 if ((process_module_umode(umode, NULL, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
1568 outpars[strlen(outpars)+1]='\0';
1569 outpars[strlen(outpars)] = parameters[1][i];
1572 for (q = 0; q < strlen(dmodes); q++)
1574 if (dmodes[q] != parameters[1][i])
1581 strcpy(dmodes,temp);
1588 if (strlen(outpars))
1594 while (i < strlen (outpars))
1596 b[z++] = outpars[i++];
1598 if (i<strlen(outpars)-1)
1600 if (((outpars[i] == '-') || (outpars[i] == '+')) && ((outpars[i+1] == '-') || (outpars[i+1] == '+')))
1602 // someones playing silly buggers and trying
1603 // to put a +- or -+ into the line...
1607 if (i == strlen(outpars)-1)
1609 if ((outpars[i] == '-') || (outpars[i] == '+'))
1617 if ((b[z] == '-') || (b[z] == '+'))
1620 if ((!strcmp(b,"+")) || (!strcmp(b,"-")))
1623 if (strlen(dmodes)>MAXMODES)
1625 dmodes[MAXMODES-1] = '\0';
1627 log(DEBUG,"Stripped mode line");
1628 log(DEBUG,"Line dest is now %s",dmodes);
1629 strncpy(dest->modes,dmodes,MAXMODES);
1636 Ptr = FindChan(parameters[0]);
1640 strncpy(s2.nick,ServerName,NICKMAX);
1641 strcpy(s2.modes,"o");
1643 process_modes(parameters,&s2,Ptr,STATUS_OP,pcnt,true,true,false);
1648 void merge_mode2(char **parameters, int pcnt, userrec* user)
1654 char outpars[MAXBUF];
1656 dest = Find(parameters[0]);
1658 // fix: ChroNiCk found this - we cant use this as debug if its null!
1661 log(DEBUG,"merge_mode on %s",dest->nick);
1664 if ((dest) && (pcnt > 1))
1666 log(DEBUG,"params > 1");
1668 char dmodes[MAXBUF];
1669 strncpy(dmodes,dest->modes,MAXBUF);
1671 strcpy(outpars,"+");
1674 if ((parameters[1][0] != '+') && (parameters[1][0] != '-'))
1677 for (int i = 0; i < strlen(parameters[1]); i++)
1679 if (parameters[1][i] == '+')
1683 if ((outpars[strlen(outpars)-1] == '+') || (outpars[strlen(outpars)-1] == '-'))
1685 outpars[strlen(outpars)-1] = '+';
1689 strcat(outpars,"+");
1695 if (parameters[1][i] == '-')
1699 if ((outpars[strlen(outpars)-1] == '+') || (outpars[strlen(outpars)-1] == '-'))
1701 outpars[strlen(outpars)-1] = '-';
1705 strcat(outpars,"-");
1712 log(DEBUG,"begin mode processing entry");
1718 log(DEBUG,"umode %c being added",parameters[1][i]);
1719 if ((!strchr(dmodes,parameters[1][i])) && (allowed_umode(parameters[1][i],user->modes,true)))
1721 char umode = parameters[1][i];
1722 log(DEBUG,"umode %c is an allowed umode",umode);
1723 if ((process_module_umode(umode, NULL, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
1725 dmodes[strlen(dmodes)+1]='\0';
1726 dmodes[strlen(dmodes)] = parameters[1][i];
1727 outpars[strlen(outpars)+1]='\0';
1728 outpars[strlen(outpars)] = parameters[1][i];
1734 // can only remove a mode they already have
1735 log(DEBUG,"umode %c being removed",parameters[1][i]);
1736 if ((allowed_umode(parameters[1][i],user->modes,false)) && (strchr(dmodes,parameters[1][i])))
1738 char umode = parameters[1][i];
1739 log(DEBUG,"umode %c is an allowed umode",umode);
1740 if ((process_module_umode(umode, NULL, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
1746 outpars[strlen(outpars)+1]='\0';
1747 outpars[strlen(outpars)] = parameters[1][i];
1750 for (q = 0; q < strlen(dmodes); q++)
1752 if (dmodes[q] != parameters[1][i])
1759 strcpy(dmodes,temp);
1766 if (strlen(outpars))
1772 while (i < strlen (outpars))
1774 b[z++] = outpars[i++];
1776 if (i<strlen(outpars)-1)
1778 if (((outpars[i] == '-') || (outpars[i] == '+')) && ((outpars[i+1] == '-') || (outpars[i+1] == '+')))
1780 // someones playing silly buggers and trying
1781 // to put a +- or -+ into the line...
1785 if (i == strlen(outpars)-1)
1787 if ((outpars[i] == '-') || (outpars[i] == '+'))
1795 if ((b[z] == '-') || (b[z] == '+'))
1798 if ((!strcmp(b,"+")) || (!strcmp(b,"-")))
1801 WriteTo(user,dest,"MODE :%s",b);
1803 if (strlen(dmodes)>MAXMODES)
1805 dmodes[MAXMODES-1] = '\0';
1807 log(DEBUG,"Stripped mode line");
1808 log(DEBUG,"Line dest is now %s",dmodes);
1809 strncpy(dest->modes,dmodes,MAXMODES);
1816 Ptr = FindChan(parameters[0]);
1819 log(DEBUG,"merge_mode2: found channel %s",Ptr->name);
1822 if ((cstatus(user,Ptr) < STATUS_HOP) && (!is_uline(user->server)))
1826 process_modes(parameters,user,Ptr,cstatus(user,Ptr),pcnt,false,false,true);