*mbuf++ = 'D';
else if (MyUser(cptr) && (chptr->mode.mode & MODE_WASDELJOINS))
*mbuf++ = 'd';
+ if (chptr->mode.mode & MODE_REGISTERED)
+ *mbuf++ = 'R';
if (chptr->mode.limit) {
*mbuf++ = 'l';
ircd_snprintf(0, pbuf, buflen, "%u", chptr->mode.limit);
MODE_NOPRIVMSGS, 'n',
MODE_REGONLY, 'r',
MODE_DELJOINS, 'D',
+ MODE_REGISTERED, 'R',
/* MODE_KEY, 'k', */
/* MODE_BAN, 'b', */
MODE_LIMIT, 'l',
mode &= (MODE_ADD | MODE_DEL | MODE_PRIVATE | MODE_SECRET | MODE_MODERATED |
MODE_TOPICLIMIT | MODE_INVITEONLY | MODE_NOPRIVMSGS | MODE_REGONLY |
- MODE_DELJOINS | MODE_WASDELJOINS);
+ MODE_DELJOINS | MODE_WASDELJOINS | MODE_REGISTERED);
if (!(mode & ~(MODE_ADD | MODE_DEL))) /* don't add empty modes... */
return;
assert(0 != mbuf);
assert(0 != (mode & (MODE_ADD | MODE_DEL)));
- if (mode == (MODE_LIMIT | ((mbuf->mb_dest & MODEBUF_DEST_BOUNCE) ? MODE_ADD : MODE_DEL))) {
+ if (mode == (MODE_LIMIT | MODE_DEL)) {
mbuf->mb_rem |= mode;
return;
}
MODE_KEY, 'k',
MODE_APASS, 'A',
MODE_UPASS, 'U',
+ MODE_REGISTERED, 'R',
/* MODE_BAN, 'b', */
MODE_LIMIT, 'l',
MODE_REGONLY, 'r',
return;
}
-/** Simple function to invalidate bans
+/** Simple function to invalidate a channel's ban cache.
*
- * This function sets all bans as being valid.
+ * This function marks all members of the channel as being neither
+ * banned nor banned.
*
* @param chan The channel to operate on.
*/
/* What we've done for mode_parse so far... */
#define DONE_LIMIT 0x01 /**< We've set the limit */
-#define DONE_KEY 0x02 /**< We've set the key */
+#define DONE_KEY_ADD 0x02 /**< We've set the key */
#define DONE_BANLIST 0x04 /**< We've sent the ban list */
#define DONE_NOTOPER 0x08 /**< We've sent a "Not oper" error */
#define DONE_BANCLEAN 0x10 /**< We've cleaned bans... */
-#define DONE_UPASS 0x20 /**< We've set user pass */
-#define DONE_APASS 0x40 /**< We've set admin pass */
+#define DONE_UPASS_ADD 0x20 /**< We've set user pass */
+#define DONE_APASS_ADD 0x40 /**< We've set admin pass */
+#define DONE_KEY_DEL 0x80 /**< We've removed the key */
+#define DONE_UPASS_DEL 0x100 /**< We've removed the user pass */
+#define DONE_APASS_DEL 0x200 /**< We've removed the admin pass */
struct ParseState {
struct ModeBuf *mbuf;
return;
}
- if (state->done & DONE_KEY) /* allow key to be set only once */
- return;
- state->done |= DONE_KEY;
+ /* allow removing and then adding key, but not adding and then removing */
+ if (state->dir == MODE_ADD)
+ {
+ if (state->done & DONE_KEY_ADD)
+ return;
+ state->done |= DONE_KEY_ADD;
+ }
+ else
+ {
+ if (state->done & (DONE_KEY_ADD | DONE_KEY_DEL))
+ return;
+ state->done |= DONE_KEY_DEL;
+ }
/* clean up the key string */
clean_key(t_str);
return;
}
- if (state->done & DONE_UPASS) /* allow upass to be set only once */
- return;
- state->done |= DONE_UPASS;
+ /* allow removing and then adding upass, but not adding and then removing */
+ if (state->dir == MODE_ADD)
+ {
+ if (state->done & DONE_UPASS_ADD)
+ return;
+ state->done |= DONE_UPASS_ADD;
+ }
+ else
+ {
+ if (state->done & (DONE_UPASS_ADD | DONE_UPASS_DEL))
+ return;
+ state->done |= DONE_UPASS_DEL;
+ }
/* clean up the upass string */
clean_key(t_str);
}
}
- if (state->done & DONE_APASS) /* allow apass to be set only once */
- return;
- state->done |= DONE_APASS;
+ /* allow removing and then adding apass, but not adding and then removing */
+ if (state->dir == MODE_ADD)
+ {
+ if (state->done & DONE_APASS_ADD)
+ return;
+ state->done |= DONE_APASS_ADD;
+ }
+ else
+ {
+ if (state->done & (DONE_APASS_ADD | DONE_APASS_DEL))
+ return;
+ state->done |= DONE_APASS_DEL;
+ }
/* clean up the apass string */
clean_key(t_str);
assert(newban->flags & (BAN_ADD|BAN_DEL));
if (newban->flags & BAN_ADD) {
size_t totlen = 0;
- /* If a less specific entry is found, fail. */
+ /* If a less specific *active* entry is found, fail. */
for (ban = *banlist; ban; ban = ban->next) {
- if (!bmatch(ban, newban)) {
+ if (!bmatch(ban, newban) && !(ban->flags & BAN_DEL)) {
if (do_free)
free_ban(newban);
return 1;
if (!state->mbuf)
return;
+ /* Local users are not permitted to change registration status */
+ if (flag_p[0] == MODE_REGISTERED && !(state->flags & MODE_PARSE_FORCE) &&
+ MyUser(state->sptr))
+ return;
+
if (state->dir == MODE_ADD) {
state->add |= flag_p[0];
state->del &= ~flag_p[0];
MODE_KEY, 'k',
MODE_APASS, 'A',
MODE_UPASS, 'U',
+ MODE_REGISTERED, 'R',
MODE_BAN, 'b',
MODE_LIMIT, 'l',
MODE_REGONLY, 'r',
if (state.chptr->mode.limit && !(state.done & DONE_LIMIT))
modebuf_mode_uint(state.mbuf, MODE_DEL | MODE_LIMIT,
state.chptr->mode.limit);
- if (*state.chptr->mode.key && !(state.done & DONE_KEY))
+ if (*state.chptr->mode.key && !(state.done & DONE_KEY_DEL))
modebuf_mode_string(state.mbuf, MODE_DEL | MODE_KEY,
state.chptr->mode.key, 0);
- if (*state.chptr->mode.upass && !(state.done & DONE_UPASS))
+ if (*state.chptr->mode.upass && !(state.done & DONE_UPASS_DEL))
modebuf_mode_string(state.mbuf, MODE_DEL | MODE_UPASS,
state.chptr->mode.upass, 0);
- if (*state.chptr->mode.apass && !(state.done & DONE_APASS))
+ if (*state.chptr->mode.apass && !(state.done & DONE_APASS_DEL))
modebuf_mode_string(state.mbuf, MODE_DEL | MODE_APASS,
state.chptr->mode.apass, 0);
}