X-Git-Url: https://jfr.im/git/irc/evilnet/x3.git/blobdiff_plain/182dd032e9ea762dcd8df317ba21cb9e9130fa88..a9b5e3de4b458f788d04a651c2d1fb95c34ac15a:/src/proto-common.c?ds=sidebyside diff --git a/src/proto-common.c b/src/proto-common.c index b639c5e..3800755 100644 --- a/src/proto-common.c +++ b/src/proto-common.c @@ -552,6 +552,7 @@ void mod_chanmode_apply(struct userNode *who, struct chanNode *channel, struct mod_chanmode *change) { struct banNode *bn; + struct exemptNode *en; unsigned int ii, jj; assert(change->argc <= change->alloc_argc); @@ -568,14 +569,14 @@ mod_chanmode_apply(struct userNode *who, struct chanNode *channel, struct mod_ch * to be more specific than an existing ban. */ for (jj=0; jjbanlist.used; ++jj) { - if (match_ircglobs(change->args[ii].hostmask, channel->banlist.list[jj]->ban)) { + if (match_ircglobs(change->args[ii].u.hostmask, channel->banlist.list[jj]->ban)) { banList_remove(&channel->banlist, channel->banlist.list[jj]); free(channel->banlist.list[jj]); jj--; } } bn = calloc(1, sizeof(*bn)); - safestrncpy(bn->ban, change->args[ii].hostmask, sizeof(bn->ban)); + safestrncpy(bn->ban, change->args[ii].u.hostmask, sizeof(bn->ban)); if (who) safestrncpy(bn->who, who->nick, sizeof(bn->who)); else @@ -585,23 +586,55 @@ mod_chanmode_apply(struct userNode *who, struct chanNode *channel, struct mod_ch break; case MODE_REMOVE|MODE_BAN: for (jj=0; jjbanlist.used; ++jj) { - if (strcmp(channel->banlist.list[jj]->ban, change->args[ii].hostmask)) + if (strcmp(channel->banlist.list[jj]->ban, change->args[ii].u.hostmask)) continue; free(channel->banlist.list[jj]); banList_remove(&channel->banlist, channel->banlist.list[jj]); break; } break; + case MODE_EXEMPT: + /* If any existing exempt is a subset of the new exempt, + * silently remove it. The new exempt is not allowed + * to be more specific than an existing exempt. + */ + for (jj=0; jjexemptlist.used; ++jj) { + if (match_ircglobs(change->args[ii].u.hostmask, channel->exemptlist.list[jj]->exempt)) { + exemptList_remove(&channel->exemptlist, channel->exemptlist.list[jj]); + free(channel->exemptlist.list[jj]); + jj--; + } + } + en = calloc(1, sizeof(*en)); + safestrncpy(en->exempt, change->args[ii].u.hostmask, sizeof(en->exempt)); + if (who) + safestrncpy(en->who, who->nick, sizeof(en->who)); + else + safestrncpy(en->who, "", sizeof(en->who)); + en->set = now; + exemptList_append(&channel->exemptlist, en); + break; + case MODE_REMOVE|MODE_EXEMPT: + for (jj=0; jjexemptlist.used; ++jj) { + if (strcmp(channel->exemptlist.list[jj]->exempt, change->args[ii].u.hostmask)) + continue; + free(channel->exemptlist.list[jj]); + exemptList_remove(&channel->exemptlist, channel->exemptlist.list[jj]); + break; + } + break; case MODE_CHANOP: + case MODE_HALFOP: case MODE_VOICE: - case MODE_VOICE|MODE_CHANOP: + case MODE_VOICE|MODE_CHANOP|MODE_HALFOP: case MODE_REMOVE|MODE_CHANOP: + case MODE_REMOVE|MODE_HALFOP: case MODE_REMOVE|MODE_VOICE: - case MODE_REMOVE|MODE_VOICE|MODE_CHANOP: + case MODE_REMOVE|MODE_VOICE|MODE_CHANOP|MODE_HALFOP: if (change->args[ii].mode & MODE_REMOVE) - change->args[ii].member->modes &= ~change->args[ii].mode; + change->args[ii].u.member->modes &= ~change->args[ii].mode; else - change->args[ii].member->modes |= change->args[ii].mode; + change->args[ii].u.member->modes |= change->args[ii].mode; break; default: assert(0 && "Invalid mode argument"); @@ -638,7 +671,8 @@ mod_chanmode(struct userNode *who, struct chanNode *channel, char **modes, unsig } int -irc_make_chanmode(struct chanNode *chan, char *out) { +irc_make_chanmode(struct chanNode *chan, char *out) +{ struct mod_chanmode change; mod_chanmode_init(&change); change.modes_set = chan->modes;