Incoming MODE processing is split into a parsing step and an execution
step, instead of a mode's effector function being involved in its own
parsing. Modes can no longer use custom logic to control their parsing,
and instead supply a combination of CHM_* flags to the parser. As a
result, we know before we try to effect any mode changes what all of
them will be.
The reauthorize hack for override is no longer necessary. A side effect
of its introduction was that `MODE #foo b x!y@z` no longer worked; in
removing it we restore that behaviour.
We gain the ability to reject various invalid inputs that:
- mutate or query unknown modes
- supply excess mode arguments
- query modes that can't be queried
In each case, whether we *should* reject it is an open question; for now
I'm rejecting the first one.
The algorithm we're using gets stuck if it has a ? and can only see a *
to feed to it, even if it could skip over that * and consume a character
following it. Remedy this by rearranging the input so * always precedes
? in runs of wildcards, so when we're matching ? we know we can skip
things.
Otherwise, sendto_channel_local_priv() will only distribute mode changes
to opers only. This is because HasPrivilege(target_p, "") will evaluate
as false due to the target not being opered.
Thanks to Devin Brown for bisecting this issue.
I'm preparing to PR a succession of privs changes with the ultimate goal
of severely limiting the scope of the binary oper/user dichotomy and
move conceptually distinct oper functions into their own privs.
Accomplishing this is a non-trivial task, and can wait, but it's
inconvenient now to have such functions enabled by the same mechanism
that grants any privs at all--so I'm moving all of them to a
transitional priv with the intention of eroding that later.