Log message:
Fixes for 3 bugs:
1) /mode <nick> -o wasn't propagated; the privileges were being set before
send_umode_out() could get at them, so the PRIV_PROPAGATE setting went
away.
2) /mode #channel +b banmask, under certain circumstances, would allow
multiple bans of the exact same mask to be added to the channel.
3) /mode #channel +b banmask would leak memory if another ban of the exact
same mask was already present on the channel (and bug #2 wasn't
triggered).
Testing:
Compiled and ran; unable to duplicate the errors, now.
git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@382
c9e4aea6-c8fd-4c43-8297-
357d70d61c8c
+2001-01-29 Kevin L. Mitchell <klmitch@mit.edu>
+
+ * ircd/channel.c (mode_parse_ban): stopper a tiny leak--if a ban
+ already existed, then the logic would (attempt to) skip it, but
+ would not free the ban string; now the ban string is free'd and
+ the ban count is decremented, releasing the ban for use
+
+ * ircd/s_user.c: make send_umode_out() take a prop argument
+ instead of testing for the PRIV_PROPAGATE privilege itself; fix
+ set_umode() to use this new argument, calculating it before
+ calculating the new privileges for a -o'd user
+
+ * ircd/m_oper.c (m_oper): pass the new prop argument to
+ send_umode_out()
+
+ * ircd/channel.c (mode_parse_ban): turn off MODE_ADD bit in bans
+ that we're not actually going to add because they already exist;
+ test that particular bit before adding to the linked list
+
+ * include/s_user.h: add a prop argument to send_umode_out() to
+ indicate whether or not to propagate the user mode
+
2001-01-24 Kevin L. Mitchell <klmitch@mit.edu>
* ircd/msgq.c: ircd_vsnprintf() returns the number of bytes that
extern int do_nick_name(char* nick);
extern int set_nick_name(struct Client* cptr, struct Client* sptr,
const char* nick, int parc, char* parv[]);
-extern void send_umode_out(struct Client* cptr, struct Client* sptr, int old);
+extern void send_umode_out(struct Client* cptr, struct Client* sptr, int old,
+ int prop);
extern int whisper(struct Client* source, const char* nick,
const char* channel, const char* text, int is_notice);
extern void send_user_info(struct Client* to, char* names, int rpl,
} else if (state->dir == MODE_ADD) {
/* if the ban already exists, don't worry about it */
if (!ircd_strcmp(ban->value.ban.banstr, t_str)) {
+ newban->flags &= ~MODE_ADD; /* don't add ban at all */
+ MyFree(newban->value.ban.banstr); /* stopper a leak */
+ state->numbans--; /* deallocate last ban */
if (state->done & DONE_BANCLEAN) /* If we're cleaning, finish */
break;
- continue;
} else if (!mmatch(ban->value.ban.banstr, t_str)) {
if (!(ban->flags & MODE_DEL))
newban->flags |= CHFL_BAN_OVERLAPPED; /* our ban overlaps */
} else if (!mmatch(t_str, ban->value.ban.banstr))
ban->flags |= MODE_DEL; /* mark ban for deletion: overlapping */
- if (!ban->next) {
+ if (!ban->next && (newban->flags & MODE_ADD)) {
ban->next = newban; /* add our ban with its flags */
break; /* get out of loop */
}
set_snomask(sptr, SNO_OPERDEFAULT, SNO_ADD);
client_set_privs(sptr);
- send_umode_out(cptr, sptr, old_mode);
+ send_umode_out(cptr, sptr, old_mode, HasPriv(sptr, PRIV_PROPAGATE));
send_reply(sptr, RPL_YOUREOPER);
sendto_opmask_butone(0, SNO_OLDSNO, "%s (%s@%s) is now operator (%c)",
/*
* added Sat Jul 25 07:30:42 EST 1992
*/
-void send_umode_out(struct Client *cptr, struct Client *sptr, int old)
+void send_umode_out(struct Client *cptr, struct Client *sptr, int old,
+ int prop)
{
int i;
struct Client *acptr;
- send_umode(NULL, sptr, old,
- SEND_UMODES & ~(HasPriv(sptr, PRIV_PROPAGATE) ? 0 : FLAGS_OPER));
+ send_umode(NULL, sptr, old, SEND_UMODES & ~(prop ? 0 : FLAGS_OPER));
for (i = HighestFd; i >= 0; i--) {
if ((acptr = LocalClientArray[i]) && IsServer(acptr) &&
unsigned int tmpmask = 0;
int snomask_given = 0;
char buf[BUFSIZE];
+ int prop = 0;
what = MODE_ADD;
* Compare new flags with old flags and send string which
* will cause servers to update correctly.
*/
- if ((setflags & FLAGS_OPER) && !IsOper(sptr)) {
- --UserStats.opers;
- client_set_privs(sptr);
- }
- if (!(setflags & FLAGS_OPER) && IsOper(sptr)) {
+ if (!(setflags & FLAGS_OPER) && IsOper(sptr)) { /* user now oper */
++UserStats.opers;
- client_set_privs(sptr);
+ client_set_privs(sptr); /* may set propagate privilege */
+ }
+ if (HasPriv(sptr, PRIV_PROPAGATE)) /* remember propagate privilege setting */
+ prop = 1;
+ if ((setflags & FLAGS_OPER) && !IsOper(sptr)) { /* user no longer oper */
+ --UserStats.opers;
+ client_set_privs(sptr); /* will clear propagate privilege */
}
if ((setflags & FLAGS_INVISIBLE) && !IsInvisible(sptr))
--UserStats.inv_clients;
if (!(setflags & FLAGS_INVISIBLE) && IsInvisible(sptr))
++UserStats.inv_clients;
- send_umode_out(cptr, sptr, setflags);
+ send_umode_out(cptr, sptr, setflags, prop);
return 0;
}