int opped_members_index = 0;
struct Membership** opped_members = NULL;
int last_oplevel = 0;
- int feat_oplevels = (chptr->mode.apass[0]) != '\0';
+ int send_oplevels = 0;
assert(0 != cptr);
assert(0 != chptr);
++number_of_ops;
else
opped_members[opped_members_index++] = member;
+ /* We also send oplevels if anyone is below the weakest level. */
+ if (OpLevel(member) < MAXOPLEVEL)
+ send_oplevels = 1;
}
/* Only handle the members with the flags that we are interested in. */
if ((member->status & CHFL_VOICED_OR_OPPED) == current_flags[flag_cnt])
if (IsChanOp(member)) /* flag_cnt == 2 or 3 */
{
/* append the absolute value of the oplevel */
- if (feat_oplevels)
+ if (send_oplevels)
loc += ircd_snprintf(0, tbuf + loc, sizeof(tbuf) - loc, "%u", last_oplevel = member->oplevel);
else
tbuf[loc++] = 'o';
msgq_append(&me, mb, tbuf);
new_mode = 0;
}
- else if (feat_oplevels && flag_cnt > 1 && last_oplevel != member->oplevel)
+ else if (send_oplevels && flag_cnt > 1 && last_oplevel != member->oplevel)
{
/*
* This can't be the first member of a (continued) BURST
}
/* if we're changing oplevels and we know the oplevel, pass it on */
- if (mbuf->mb_channel->mode.apass[0]
- && (MB_TYPE(mbuf, i) & MODE_CHANOP)
+ if ((MB_TYPE(mbuf, i) & MODE_CHANOP)
&& MB_OPLEVEL(mbuf, i) < MAXOPLEVEL)
*strptr_i += ircd_snprintf(0, strptr + *strptr_i, BUFSIZE - *strptr_i,
" %s%s:%d",
modebuf_flush_int(mbuf, 0);
}
+/** Check a channel for join-delayed members.
+ * @param[in] chan Channel to search.
+ * @return Non-zero if any members are join-delayed; false if none are.
+ */
+static int
+find_delayed_joins(const struct Channel *chan)
+{
+ const struct Membership *memb;
+ for (memb = chan->members; memb; memb = memb->next_member)
+ if (IsDelayedJoin(memb))
+ return 1;
+ return 0;
+}
+
/** The exported binding for modebuf_flush()
*
* @param mbuf The mode buffer to flush.
int
modebuf_flush(struct ModeBuf *mbuf)
{
- struct Membership *memb;
-
- /* Check if MODE_WASDELJOINS should be set */
- if (!(mbuf->mb_channel->mode.mode & (MODE_DELJOINS | MODE_WASDELJOINS))
- && (mbuf->mb_rem & MODE_DELJOINS)) {
- for (memb = mbuf->mb_channel->members; memb; memb = memb->next_member) {
- if (IsDelayedJoin(memb)) {
- mbuf->mb_channel->mode.mode |= MODE_WASDELJOINS;
- mbuf->mb_add |= MODE_WASDELJOINS;
- mbuf->mb_rem &= ~MODE_WASDELJOINS;
- break;
- }
- }
+ /* Check if MODE_WASDELJOINS should be set: */
+ /* Must be set if going -D and some clients are hidden */
+ if ((mbuf->mb_rem & MODE_DELJOINS)
+ && !(mbuf->mb_channel->mode.mode & (MODE_DELJOINS | MODE_WASDELJOINS))
+ && find_delayed_joins(mbuf->mb_channel)) {
+ mbuf->mb_channel->mode.mode |= MODE_WASDELJOINS;
+ mbuf->mb_add |= MODE_WASDELJOINS;
+ mbuf->mb_rem &= ~MODE_WASDELJOINS;
+ }
+ /* Must be cleared if +D is set */
+ if ((mbuf->mb_add & MODE_DELJOINS)
+ && ((mbuf->mb_channel->mode.mode & (MODE_WASDELJOINS | MODE_WASDELJOINS))
+ == (MODE_WASDELJOINS | MODE_WASDELJOINS))) {
+ mbuf->mb_channel->mode.mode &= ~MODE_WASDELJOINS;
+ mbuf->mb_add &= ~MODE_WASDELJOINS;
+ mbuf->mb_rem |= MODE_WASDELJOINS;
}
return modebuf_flush_int(mbuf, 1);
old_ban->banstr[old_ban->nu_len] = new_ban->banstr[new_ban->nu_len] = '@';
if (res)
return res;
- /* Compare the addresses. */
- return !ipmask_check(&new_ban->address, &old_ban->address, old_ban->addrbits);
+ /* If the old ban's mask mismatches, cannot be a superset. */
+ if (!ipmask_check(&new_ban->address, &old_ban->address, old_ban->addrbits))
+ return 1;
+ /* Otherwise it depends on whether the old ban's text is a superset
+ * of the new. */
+ return mmatch(old_ban->banstr, new_ban->banstr);
}
/** Add a ban from a ban list and mark bans that should be removed
SetOpLevel(member, state->cli_change[i].oplevel);
else if (!state->member)
SetOpLevel(member, MAXOPLEVEL);
- else if (!state->chptr->mode.apass[0] || OpLevel(state->member) == MAXOPLEVEL)
- SetOpLevel(member, MAXOPLEVEL);
+ else if (OpLevel(state->member) >= MAXOPLEVEL)
+ SetOpLevel(member, OpLevel(state->member));
else
SetOpLevel(member, OpLevel(state->member) + 1);
}
state->add &= ~MODE_SECRET;
state->del |= MODE_SECRET;
}
- if (flag_p[0] & MODE_DELJOINS) {
- state->add &= ~MODE_WASDELJOINS;
- state->del |= MODE_WASDELJOINS;
- }
} else {
state->add &= ~flag_p[0];
state->del |= flag_p[0];
void CheckDelayedJoins(struct Channel *chan)
{
- struct Membership *memb2;
-
- if (chan->mode.mode & MODE_WASDELJOINS) {
- for (memb2=chan->members;memb2;memb2=memb2->next_member)
- if (IsDelayedJoin(memb2))
- break;
-
- if (!memb2) {
- /* clear +d */
- chan->mode.mode &= ~MODE_WASDELJOINS;
- sendcmdto_channel_butserv_butone(&his, CMD_MODE, chan, NULL, 0,
- "%H -d", chan);
- }
+ if ((chan->mode.mode & MODE_WASDELJOINS) && !find_delayed_joins(chan)) {
+ chan->mode.mode &= ~MODE_WASDELJOINS;
+ sendcmdto_channel_butserv_butone(&his, CMD_MODE, chan, NULL, 0,
+ "%H -d", chan);
}
}