* who then will educate them on the use of Apass/upass.
*/
- if (!(chptr->mode.mode & MODE_APASS)) /* If no Apass, destroy now. */
+ if (!chptr->mode.apass[0]) /* If no Apass, destroy now. */
destruct_channel(chptr);
else if (TStime() - chptr->creationtime < 172800) /* Channel younger than 48 hours? */
schedule_destruct_event_1m(chptr); /* Get rid of it in approximately 4-5 minutes */
}
}
-/** @page zombie Explaination of Zombies
+/** @page zombie Explanation of Zombies
+ *
+ * Synopsis:
+ *
+ * A channel member is turned into a zombie when he is kicked from a
+ * channel but his server has not acknowledged the kick. Servers that
+ * see the member as a zombie can accept actions he performed before
+ * being kicked, without allowing chanop operations from outsiders or
+ * desyncing the network.
*
* Consider:
* <pre>
}
/* If a non-service user is trying to force it, refuse. */
- if (state->flags & MODE_PARSE_FORCE && !IsChannelService(state->sptr)) {
+ if (state->flags & MODE_PARSE_FORCE && MyUser(state->sptr)
+ && !HasPriv(state->sptr, PRIV_APASS_OPMODE)) {
send_reply(state->sptr, ERR_NOTMANAGER, state->chptr->chname,
"Use /JOIN", state->chptr->chname, " <AdminPass>.");
return;
}
/* If a non-service user is trying to force it, refuse. */
- if (state->flags & MODE_PARSE_FORCE && !IsChannelService(state->sptr)) {
+ if (state->flags & MODE_PARSE_FORCE && MyUser(state->sptr)
+ && !HasPriv(state->sptr, PRIV_APASS_OPMODE)) {
send_reply(state->sptr, ERR_NOTMANAGER, state->chptr->chname,
"Use /JOIN", state->chptr->chname, " <AdminPass>.");
return;
"\" to remove the password and then immediately set a new one. "
"IMPORTANT: YOU CANNOT RECOVER THIS PASSWORD, EVER; "
"WRITE THE PASSWORD DOWN (don't store this rescue password on disk)! "
- "Now set the channel user password (+u).");
+ "Now set the channel user password (+U).");
}
} else { /* remove the old apass */
*state->chptr->mode.apass = '\0';
* @param[in] newban Ban (or exception) to add (or remove).
* @return Zero if \a newban could be applied, non-zero if not.
*/
-int apply_ban(struct Ban **banlist, struct Ban *newban)
+int apply_ban(struct Ban **banlist, struct Ban *newban, int do_free)
{
struct Ban *ban;
size_t count = 0;
/* If a less specific entry is found, fail. */
for (ban = *banlist; ban; ban = ban->next) {
if (!bmatch(ban, newban)) {
- free_ban(newban);
+ if (do_free)
+ free_ban(newban);
return 1;
}
if (!(ban->flags & (BAN_OVERLAPPED|BAN_DEL))) {
/* Mark more specific entries and add this one to the end of the list. */
while ((ban = *banlist) != NULL) {
if (!bmatch(newban, ban)) {
- ban->flags |= BAN_OVERLAPPED;
+ ban->flags |= BAN_OVERLAPPED | BAN_DEL;
}
banlist = &ban->next;
}
/* Mark more specific entries. */
for (ban = *banlist; ban; ban = ban->next) {
if (!bmatch(newban, ban)) {
- ban->flags |= BAN_OVERLAPPED;
+ ban->flags |= BAN_OVERLAPPED | BAN_DEL;
remove_count++;
}
}
+ if (remove_count)
+ return 0;
/* If no matches were found, fail. */
- if (!remove_count) {
+ if (do_free)
free_ban(newban);
- return 3;
- }
- return 0;
+ else
+ MyFree(newban->banstr);
+ return 3;
}
- free_ban(newban);
+ if (do_free)
+ free_ban(newban);
return 4;
}
mode_parse_ban(struct ParseState *state, int *flag_p)
{
char *t_str, *s;
- struct Ban *ban, *newban = 0;
+ struct Ban *ban, *newban;
if (state->parc <= 0) { /* Not enough args, send ban list */
if (MyUser(state->sptr) && !(state->done & DONE_BANLIST)) {
return;
}
- if (!state->chptr->banlist) {
- state->chptr->banlist = newban; /* add our ban with its flags */
- state->done |= DONE_BANCLEAN;
- return;
- }
-
/* Clear all ADD/DEL/OVERLAPPED flags from ban list. */
if (!(state->done & DONE_BANCLEAN)) {
for (ban = state->chptr->banlist; ban; ban = ban->next)
set_ban_mask(newban, collapse(pretty_mask(t_str)));
newban->who = cli_name(state->sptr);
newban->when = TStime();
- apply_ban(&state->chptr->banlist, newban);
+ apply_ban(&state->chptr->banlist, newban, 0);
}
/*
continue;
} else if (ban->flags & BAN_DEL) { /* Deleted a ban? */
modebuf_mode_string(state->mbuf, MODE_DEL | MODE_BAN,
- ban->banstr,
- state->flags & MODE_PARSE_SET);
+ ban->banstr, 1);
if (state->flags & MODE_PARSE_SET) { /* Ok, make it take effect */
if (prevban) /* clip it out of the list... */
} else {
/* add the ban to the buffer */
modebuf_mode_string(state->mbuf, MODE_ADD | MODE_BAN,
- ban->banstr,
- !(state->flags & MODE_PARSE_SET));
+ ban->banstr, 1);
if (state->flags & MODE_PARSE_SET) { /* create a new ban */
newban = make_ban(ban->banstr);