📄 m_mode.c
字号:
REQUIRE_PARAMETER() if (!(who = find_chasing(cptr, param, &chasing))) break; if (!who->user) break; /* codemastr: your patch is a good idea here, but look at the member->flags stuff longer down. this caused segfaults */ if (!(membership = find_membership_link(who->user->channel, chptr))) { sendto_one(cptr, err_str(ERR_USERNOTINCHANNEL), me.name, cptr->name, who->name, chptr->chname); break; } member = find_member_link(chptr->members, who); if (!member) { /* should never happen */ sendto_realops("crap! find_membership_link && !find_member_link !!. Report to unreal team"); break; } /* we make the rules, we bend the rules */ if (IsServer(cptr) || IsULine(cptr)) goto breaktherules; /* Services are special! */ if (IsServices(member->cptr) && MyClient(cptr) && !IsNetAdmin(cptr) && (what == MODE_DEL)) { char errbuf[NICKLEN+50]; ircsprintf(errbuf, "%s is a network service", member->cptr->name); sendto_one(cptr, err_str(ERR_CANNOTCHANGECHANMODE), me.name, cptr->name, modechar, errbuf); break; } if (is_chanowner(member->cptr, chptr) && member->cptr != cptr && !is_chanowner(cptr, chptr) && !IsServer(cptr) && !IsULine(cptr) && !opermode && !samode_in_progress && (what == MODE_DEL)) { if (MyClient(cptr)) { char errbuf[NICKLEN+30]; ircsprintf(errbuf, "%s is a channel owner", member->cptr->name); sendto_one(cptr, err_str(ERR_CANNOTCHANGECHANMODE), me.name, cptr->name, modechar, errbuf); break; } else if (IsOper(cptr)) opermode = 1; } if (is_chanprot(member->cptr, chptr) && member->cptr != cptr && !is_chanowner(cptr, chptr) && !IsServer(cptr) && !opermode && !samode_in_progress && modetype != MODE_CHANOWNER && (what == MODE_DEL)) { if (MyClient(cptr)) { char errbuf[NICKLEN+30]; ircsprintf(errbuf, "%s is a channel admin", member->cptr->name); sendto_one(cptr, err_str(ERR_CANNOTCHANGECHANMODE), me.name, cptr->name, modechar, errbuf); break; } else if (IsOper(cptr)) opermode = 1; } breaktherules: tmp = member->flags; if (what == MODE_ADD) member->flags |= modetype; else member->flags &= ~modetype; if ((tmp == member->flags) && (bounce || !IsULine(cptr))) break; /* It's easier to undo the mode here instead of later * when you call make_mode_str for a bounce string. * Why set it if it will be instantly removed? * Besides, pvar keeps a log of it. */ if (bounce) member->flags = tmp; if (modetype == MODE_CHANOWNER) tc = 'q'; if (modetype == MODE_CHANPROT) tc = 'a'; if (modetype == MODE_CHANOP) tc = 'o'; if (modetype == MODE_HALFOP) tc = 'h'; if (modetype == MODE_VOICE) tc = 'v'; /* Make sure membership->flags and member->flags is the same */ membership->flags = member->flags; (void)ircsprintf(pvar[*pcount], "%c%c%s", what == MODE_ADD ? '+' : '-', tc, who->name); (*pcount)++; break; case MODE_LIMIT: if (what == MODE_ADD) { if (!param) { retval = 0; break; } retval = 1; tmp = atoi(param); if (chptr->mode.limit == tmp) break; chptr->mode.limit = tmp; } else { retval = 0; if (!chptr->mode.limit) break; chptr->mode.limit = 0; } break; case MODE_KEY: if (!param || *pcount >= MAXMODEPARAMS) { retval = 0; break; } retval = 1; for (x = 0; x < *pcount; x++) { if (pvar[x][1] == 'k') { /* don't allow user to change key * more than once per command. */ retval = 0; break; } } if (retval == 0) /* you can't break a case from loop */ break; if (what == MODE_ADD) { if (!bounce) { /* don't do the mode at all. */ char *tmp; if ((tmp = strchr(param, ' '))) *tmp = '\0'; if ((tmp = strchr(param, ':'))) *tmp = '\0'; if ((tmp = strchr(param, ','))) *tmp = '\0'; if (*param == '\0') break; if (strlen(param) > KEYLEN) param[KEYLEN] = '\0'; if (!strcmp(chptr->mode.key, param)) break; strncpyzt(chptr->mode.key, param, sizeof(chptr->mode.key)); } tmpstr = param; } else { if (!*chptr->mode.key) break; /* no change */ strncpyzt(tmpbuf, chptr->mode.key, sizeof(tmpbuf)); tmpstr = tmpbuf; if (!bounce) strcpy(chptr->mode.key, ""); } retval = 1; (void)ircsprintf(pvar[*pcount], "%ck%s", what == MODE_ADD ? '+' : '-', tmpstr); (*pcount)++; break; case MODE_BAN: if (!param || *pcount >= MAXMODEPARAMS) { retval = 0; break; } retval = 1; tmpstr = clean_ban_mask(param, what, cptr); if (BadPtr(tmpstr)) break; /* ignore ban, but eat param */ if ((tmpstr[0] == '~') && MyClient(cptr) && !bounce) { /* extban: check access if needed */ Extban *p = findmod_by_bantype(tmpstr[1]); if (p && p->is_ok) { if (!p->is_ok(cptr, chptr, tmpstr, EXBCHK_ACCESS, what, EXBTYPE_BAN)) { if (IsAnOper(cptr)) { /* TODO: send operoverride notice */ } else { p->is_ok(cptr, chptr, tmpstr, EXBCHK_ACCESS_ERR, what, EXBTYPE_BAN); break; } } if (!p->is_ok(cptr, chptr, tmpstr, EXBCHK_PARAM, what, EXBTYPE_BAN)) break; } } /* For bounce, we don't really need to worry whether * or not it exists on our server. We'll just always * bounce it. */ if (!bounce && ((what == MODE_ADD && add_listmode(&chptr->banlist, cptr, chptr, tmpstr)) || (what == MODE_DEL && del_listmode(&chptr->banlist, chptr, tmpstr)))) break; /* already exists */ (void)ircsprintf(pvar[*pcount], "%cb%s", what == MODE_ADD ? '+' : '-', tmpstr); (*pcount)++; break; case MODE_EXCEPT: if (!param || *pcount >= MAXMODEPARAMS) { retval = 0; break; } retval = 1; tmpstr = clean_ban_mask(param, what, cptr); if (BadPtr(tmpstr)) break; /* ignore except, but eat param */ if ((tmpstr[0] == '~') && MyClient(cptr) && !bounce) { /* extban: check access if needed */ Extban *p = findmod_by_bantype(tmpstr[1]); if (p && p->is_ok) { if (!p->is_ok(cptr, chptr, tmpstr, EXBCHK_ACCESS, what, EXBTYPE_EXCEPT)) { if (IsAnOper(cptr)) { /* TODO: send operoverride notice */ } else { p->is_ok(cptr, chptr, tmpstr, EXBCHK_ACCESS_ERR, what, EXBTYPE_EXCEPT); break; } } if (!p->is_ok(cptr, chptr, tmpstr, EXBCHK_PARAM, what, EXBTYPE_EXCEPT)) break; } } /* For bounce, we don't really need to worry whether * or not it exists on our server. We'll just always * bounce it. */ if (!bounce && ((what == MODE_ADD && add_listmode(&chptr->exlist, cptr, chptr, tmpstr)) || (what == MODE_DEL && del_listmode(&chptr->exlist, chptr, tmpstr)))) break; /* already exists */ (void)ircsprintf(pvar[*pcount], "%ce%s", what == MODE_ADD ? '+' : '-', tmpstr); (*pcount)++; break; case MODE_INVEX: if (!param || *pcount >= MAXMODEPARAMS) { retval = 0; break; } retval = 1; tmpstr = clean_ban_mask(param, what, cptr); if (BadPtr(tmpstr)) break; /* ignore except, but eat param */ /* For bounce, we don't really need to worry whether * or not it exists on our server. We'll just always * bounce it. */ if (!bounce && ((what == MODE_ADD && add_listmode(&chptr->invexlist, cptr, chptr, tmpstr)) || (what == MODE_DEL && del_listmode(&chptr->invexlist, chptr, tmpstr)))) break; /* already exists */ (void)ircsprintf(pvar[*pcount], "%cI%s", what == MODE_ADD ? '+' : '-', tmpstr); (*pcount)++; break; case MODE_LINK: if (IsULine(cptr) || IsServer(cptr)) { goto linkok; } if (MyClient(cptr) && !is_chanowner(cptr, chptr) && !op_can_override(cptr) && !samode_in_progress) { sendto_one(cptr, err_str(ERR_CHANOWNPRIVNEEDED), me.name, cptr->name, chptr->chname); break; } if (!chptr->mode.limit && what == MODE_ADD) { sendto_one(cptr, err_str(ERR_CANNOTCHANGECHANMODE), me.name, cptr->name, 'L', "+l must be set"); break; } linkok: retval = 1; for (x = 0; x < *pcount; x++) { if (pvar[x][1] == 'L') { /* don't allow user to change link * more than once per command. */ retval = 0; break; } } if (retval == 0) /* you can't break a case from loop */ break; if (what == MODE_ADD) { char *tmp; if (!param || *pcount >= MAXMODEPARAMS) { retval = 0; break; } if (strchr(param, ',')) break; if (!IsChannelName(param)) { if (MyClient(cptr)) sendto_one(cptr, err_str(ERR_NOSUCHCHANNEL), me.name, cptr->name, param); break; } /* Now make it a clean channelname.. This has to be done before all checking * because it could have been changed later to something disallowed (like * self-linking). -- Syzop */ strlcpy(tmpbuf, param, CHANNELLEN+1); clean_channelname(tmpbuf); /* don't allow linking to local chans either.. */ if ((tmp = strchr(tmpbuf, ':'))) *tmp = '\0'; if (!stricmp(tmpbuf, chptr->mode.link)) break; if (!stricmp(tmpbuf, chptr->chname)) { if (MyClient(cptr)) sendto_one(cptr, err_str(ERR_CANNOTCHANGECHANMODE), me.name, cptr->name, 'L', "a channel cannot be linked to itself"); break; } if (!bounce) /* don't do the mode at all. */ { strncpyzt(chptr->mode.link, tmpbuf, sizeof(chptr->mode.link)); tmpstr = tmpbuf; } else tmpstr = param; /* Use the original value if bounce?? -- Syzop */ } else { if (!*chptr->mode.link) break; /* no change */ strncpyzt(tmpbuf, chptr->mode.link, sizeof(tmpbuf)); tmpstr = tmpbuf; if (!bounce) { strcpy(chptr->mode.link, ""); } } retval = 1; (void)ircsprintf(pvar[*pcount], "%cL%s", what == MODE_ADD ? '+' : '-', tmpstr); (*pcount)++; break; case MODE_FLOODLIMIT: retval = 1; for (x = 0; x < *pcount; x++) { if (pvar[x][1] == 'f') { /* don't allow user to change flood * more than once per command. */ retval = 0; break; } } if (retval == 0) /* you can't break a case from loop */ break;#ifndef NEWCHFLOODPROT if (what == MODE_ADD) { if (!bounce) /* don't do the mode at all. */ { if (!param || *pcount >= MAXMODEPARAMS) { retval = 0; break; } /* like 1:1 and if its less than 3 chars then ahem.. */ if (strlen(param) < 3) { break; } /* may not contain other chars than 0123456789: & NULL */ hascolon = 0; for (xp = param; *xp; xp++) { if (*xp == ':') hascolon++; /* fast alpha check */ if (((*xp < '0') || (*xp > '9')) && (*xp != ':') && (*xp != '*')) goto break_flood; /* uh oh, not the first char */ if (*xp == '*' && (xp != param)) goto break_flood; } /* We can avoid 2 strchr() and a strrchr() like this * it should be much faster. -- codemastr */ if (hascolon != 1) break; if (*param == '*') { xzi = 1; // chptr->mode.kmode = 1; } else { xzi = 0; // chptr->mode.kmode = 0; } xp = index(param, ':'); *xp = '\0'; xxi = atoi((*param == '*' ? (param + 1) : param)); xp++; xyi = atoi(xp); if (xxi > 500 || xyi > 500) break; xp--; *xp = ':'; if ((xxi == 0) || (xyi == 0)) break; if ((chptr->mode.msgs == xxi) && (chptr->mode.per == xyi) && (chptr->mode.kmode == xzi)) break; chptr->mode.msgs = xxi; chptr->mode.per = xyi; chptr->mode.kmode = xzi; } tmpstr = param; retval = 1; } else { if (!chptr->mode.msgs || !chptr->mode.per) break; /* no change */ ircsprintf(tmpbuf, (chptr->mode.kmode > 0 ? "*%i:%i" : "%i:%i"), chptr->mode.msgs, chptr->mode.per); tmpstr = tmpbuf; if (!bounce) { chptr->mode.msgs = chptr->mode.per = chptr->mode.kmode = 0; } retval = 0; }#else /* NEW */ if (what == MODE_ADD) { if (!bounce) /* don't do the mode at all. */ {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -