1
0
mirror of https://github.com/anope/anope.git synced 2026-06-28 03:36:37 +02:00

BUILD : 1.7.8 (646) BUGS : 327 329 334 335 NOTES : Fixed quite a few bugs with mode handling (not always removed correctly, added/removed modes were split), fixed a segfault in chan_set_correct_modes, fixed some issues with topic setting, made stripModePrefix really stripping the mode prefix instead of the first char

git-svn-id: svn://svn.anope.org/anope/trunk@646 31f1291d-b8d6-0310-a050-a5561fc1590b


git-svn-id: http://anope.svn.sourceforge.net/svnroot/anope/trunk@494 5417fbe8-f217-4b02-8779-1006273d7864
This commit is contained in:
geniusdex geniusdex@31f1291d-b8d6-0310-a050-a5561fc1590b
2005-03-28 12:59:44 +00:00
parent 0783c0d875
commit b30ca2f8f2
6 changed files with 202 additions and 120 deletions
+5
View File
@@ -10,6 +10,11 @@ Provided by Anope Dev. <dev@anope.org> - 2005
02/13 A Internal Event support, see EVENTS in the doc folder for help [ #00]
02/05 A Support for Unreal 3.2 +I channel mode. [ #00]
02/03 A Merged anope-win32 branch into the main, now Win32 ready. [ #00]
03/28 F Segfault on joining unregistered channels in some cases. [#327]
03/28 F Adding and removing modes are now merged per user while syncing. [#329]
03/28 F Modes not being correctly removed from all users. [#335]
03/28 F Topics not always set on channel creation. [#334]
03/26 F stripModePrefix not checking if it was stripping a mode prefix. [ #00]
03/26 F Memleak in nickIsServices() [ #00]
03/22 F Wrong behaviour of /ns update for channel founders. [#323]
03/21 F Topics being set too often during bursts. [ #00]
+1 -1
View File
@@ -128,7 +128,7 @@ E void do_sjoin(const char *source, int ac, char **av);
E void do_topic(const char *source, int ac, char **av);
E void do_mass_mode(char *modes);
E void chan_set_correct_modes(User * user, Channel * c);
E void chan_set_correct_modes(User * user, Channel * c, int give_modes);
E void restore_unsycned_topics(void);
#define whosends(ci) ((!(ci) || !((ci)->botflags & BS_SYMBIOSIS) || !(ci)->bi || !(ci)->c || (ci)->c->usercount < BSMinUsers) ? s_ChanServ : (ci)->bi->nick)
+189 -116
View File
@@ -161,6 +161,10 @@ void chan_remove_user_status(Channel * chan, User * user, int16 status)
{
struct u_chanlist *uc;
if (debug >= 2)
alog("debug: removing user status (%d) from %s for %s", status,
user->nick, chan->name);
for (uc = user->chans; uc; uc = uc->next) {
if (uc->chan == chan) {
uc->status &= ~status;
@@ -175,14 +179,15 @@ void chan_set_modes(const char *source, Channel * chan, int ac, char **av,
int check)
{
int add = 1;
int servermode = !!strchr(source, '.');
char *modes = av[0], mode;
CBMode *cbm;
CMMode *cmm;
CUMode *cum;
unsigned char botmode = 0;
BotInfo *bi;
char *lastnick = NULL;
User *user;
int i, real_ac = ac;
char **real_av = av;
if (debug)
alog("debug: Changing modes for %s to %s", chan->name,
@@ -208,8 +213,6 @@ void chan_set_modes(const char *source, Channel * chan, int ac, char **av,
}
if ((cum = &cumodes[(int) mode])->status != 0) {
User *user;
if (ac == 0) {
alog("channel: mode %c%c with no parameter (?) for channel %s", add ? '+' : '-', mode, chan->name);
continue;
@@ -247,53 +250,11 @@ void chan_set_modes(const char *source, Channel * chan, int ac, char **av,
alog("debug: Setting %c%c on %s for %s", (add ? '+' : '-'),
mode, chan->name, user->nick);
if (add) {
/*
if they are in the uline server list we assume they can
have the mode - yes woke up in the middle of the night to
add this.. - TSL
*/
if (is_ulined(user->server->name)) {
chan_set_user_status(chan, user, cum->status);
continue;
}
/* Fixes bug #68
- might be a bit ugly but it works, the idea is that since the
is_valid function strips out all of the modes there is no point
in sending it over and over again
*/
if (check) {
if (check == 2 && cum->is_valid) {
if (debug) {
alog("debug: Modes already removed, calling remove_user_status() to clean up");
}
chan_remove_user_status(chan, user, cum->status);
continue;
} else if (cum->is_valid
&& !cum->is_valid(user, chan, servermode)) {
if (debug) {
alog("debug: Modes already sent calling remove_user_status() to clean up");
}
chan_remove_user_status(chan, user, cum->status);
if (!lastnick) {
check = 2;
lastnick = sstrdup(user->nick);
} else {
if (stricmp(user->nick, lastnick)) {
check = 1;
}
}
continue;
} else {
chan_set_user_status(chan, user, cum->status);
}
} else {
chan_set_user_status(chan, user, cum->status);
}
} else {
if (add)
chan_set_user_status(chan, user, cum->status);
else
chan_remove_user_status(chan, user, cum->status);
}
} else if ((cbm = &cbmodes[(int) mode])->flag != 0) {
if (add)
chan->mode |= cbm->flag;
@@ -319,12 +280,28 @@ void chan_set_modes(const char *source, Channel * chan, int ac, char **av,
ac--;
av++;
add ? cmm->addmask(chan, *av) : cmm->delmask(chan, *av);
if (add)
cmm->addmask(chan, *av);
else
cmm->delmask(chan, *av);
}
}
if (check)
if (check) {
check_modes(chan);
if (check < 2) {
/* Walk through all users we've set modes for and see if they are
* valid. Invalid modes (like +o with SECUREOPS on) will be removed
*/
real_ac--;
real_av++;
for (i = 0; i < real_ac; i++) {
if ((user = finduser(*av)) && is_on_chan(chan, user))
chan_set_correct_modes(user, chan, 0);
}
}
}
}
/*************************************************************************/
@@ -335,6 +312,10 @@ void chan_set_user_status(Channel * chan, User * user, int16 status)
{
struct u_chanlist *uc;
if (debug >= 2)
alog("debug: setting user status (%d) on %s for %s", status,
user->nick, chan->name);
if (HelpChannel && ircd->supporthelper
&& (status == CUS_OP || status == (CUS_PROTECT | CUS_OP)
|| status == (CUS_OWNER | CUS_OP))
@@ -573,8 +554,8 @@ void do_join(const char *source, int ac, char **av)
continue;
chan = findchan(s);
join_user_update(user, chan, s);
chan_set_correct_modes(user, chan);
chan = join_user_update(user, chan, s);
chan_set_correct_modes(user, chan, 1);
}
}
@@ -739,6 +720,7 @@ void do_sjoin(const char *source, int ac, char **av)
char *s, *end, cubuf[7], *end2, *cumodes[6];
int is_sqlined = 0;
int ts = 0;
int is_created = 0;
serv = findserver(servlist, source);
@@ -837,13 +819,13 @@ void do_sjoin(const char *source, int ac, char **av)
for (i = 1; i < end2 - cubuf; i++)
cumodes[i] = user->nick;
chan_set_modes(source, c, 1 + (end2 - cubuf - 1),
cumodes, 1);
cumodes, 2);
}
if (c->ci && (!serv || is_sync(serv))
&& !c->topic_sync)
restore_topic(c->name);
chan_set_correct_modes(user, c);
chan_set_correct_modes(user, c, 1);
}
}
@@ -856,7 +838,7 @@ void do_sjoin(const char *source, int ac, char **av)
/* Set the timestamp */
c->creation_time = ts;
/* We now update the channel mode. */
chan_set_modes(source, c, ac - 3, &av[2], 1);
chan_set_modes(source, c, ac - 3, &av[2], 2);
}
/* Unreal just had to be different */
@@ -913,10 +895,10 @@ void do_sjoin(const char *source, int ac, char **av)
for (i = 1; i < end2 - cubuf; i++)
cumodes[i] = user->nick;
chan_set_modes(source, c, 1 + (end2 - cubuf - 1),
cumodes, 1);
cumodes, 2);
}
chan_set_correct_modes(user, c);
chan_set_correct_modes(user, c, 1);
}
}
@@ -984,10 +966,10 @@ void do_sjoin(const char *source, int ac, char **av)
for (i = 1; i < end2 - cubuf; i++)
cumodes[i] = user->nick;
chan_set_modes(source, c, 1 + (end2 - cubuf - 1),
cumodes, 1);
cumodes, 2);
}
chan_set_correct_modes(user, c);
chan_set_correct_modes(user, c, 1);
}
}
@@ -1018,6 +1000,8 @@ void do_sjoin(const char *source, int ac, char **av)
return;
c = findchan(av[1]);
if (!c)
is_created = 1;
if (ircd->chansqline) {
if (!c)
is_sqlined = check_chan_sqline(av[1]);
@@ -1028,7 +1012,9 @@ void do_sjoin(const char *source, int ac, char **av)
} else {
c = join_user_update(user, c, av[1]);
c->creation_time = ts;
chan_set_correct_modes(user, c);
if (is_created && c->ci)
restore_topic(c->name);
chan_set_correct_modes(user, c, 1);
}
}
}
@@ -1229,80 +1215,167 @@ void add_invite(Channel * chan, char *mask)
/*************************************************************************/
/* Set the correct modes for the given user on the given channel. Ignored
* users won't get any modes set this way. -GD
*/
void chan_set_correct_modes(User * user, Channel * c)
/**
* Set the correct modes, or remove the ones granted without permission,
* for the specified user on ths specified channel. This doesn't give
* modes to ignored users, but does remove them if needed.
* @param user The user to give/remove modes to/from
* @param c The channel to give/remove modes on
* @param give_modes Set to 1 to give modes, 0 to not give modes
* @return void
**/
void chan_set_correct_modes(User * user, Channel * c, int give_modes)
{
char *tmp;
char modebuf[BUFSIZE];
char userbuf[BUFSIZE];
int status;
int add_modes = 0;
int rem_modes = 0;
ChannelInfo *ci;
ci = c->ci;
if (!c || !(ci = c->ci))
return;
if (!ci || (ci->flags & CI_VERBOTEN) || (*(c->name) == '+'))
if ((ci->flags & CI_VERBOTEN) || (*(c->name) == '+'))
return;
if ((ci->flags & CI_SECURE) && !nick_identified(user))
return;
if (get_ignore(user->nick) != NULL)
status = chan_get_user_status(c, user);
if (debug >= 2)
alog("debug: Setting correct user modes for %s on %s (current status: %d, %sgiving modes)", user->nick, c->name, status, (give_modes ? "" : "not "));
if (give_modes && (get_ignore(user->nick) == NULL)) {
if (ircd->owner
&&
(((ci->flags & CI_SECUREFOUNDER) && is_real_founder(user, ci))
|| (!(ci->flags & CI_SECUREFOUNDER) && is_founder(user, ci))))
add_modes |= (CUS_OWNER | CUS_OP);
else if ((ircd->protect || ircd->admin)
&& check_access(user, ci, CA_AUTOPROTECT))
add_modes |= (CUS_PROTECT | CUS_OP);
else if (check_access(user, ci, CA_AUTOOP))
add_modes |= CUS_OP;
else if (ircd->halfop && check_access(user, ci, CA_AUTOHALFOP))
add_modes |= CUS_HALFOP;
else if (check_access(user, ci, CA_AUTOVOICE))
add_modes |= CUS_VOICE;
}
/* We check if every mode they have is legally acquired here, and remove
* the modes that they're not allowed to have. But only if SECUREOPS is
* on, because else every mode is legal. -GD
*/
if (ci->flags & CI_SECUREOPS) {
if (ircd->owner && (status & CUS_OWNER)
&&
!(((ci->flags & CI_SECUREFOUNDER) && is_real_founder(user, ci))
|| (!(ci->flags & CI_SECUREFOUNDER)
&& is_founder(user, ci))))
rem_modes |= CUS_OWNER;
if ((ircd->protect || ircd->admin) && (status & CUS_PROTECT)
&& !check_access(user, ci, CA_AUTOPROTECT))
rem_modes |= CUS_PROTECT;
if ((status & CUS_OP) && !check_access(user, ci, CA_AUTOOP))
rem_modes |= CUS_OP;
if (ircd->halfop && (status & CUS_HALFOP)
&& !check_access(user, ci, CA_AUTOHALFOP))
rem_modes |= CUS_HALFOP;
}
/* No modes to add or remove, exit function -GD */
if (!add_modes && !rem_modes)
return;
status = chan_get_user_status(c, user);
if (ircd->owner
&& (((ci->flags & CI_SECUREFOUNDER) && is_real_founder(user, ci))
|| (!(ci->flags & CI_SECUREFOUNDER)
&& is_founder(user, ci)))) {
if (!(status & CUS_OWNER)) {
/* No need for strn* functions for modebuf, as every possible string
* will always fit in. -GD
*/
strcpy(modebuf, "");
strcpy(userbuf, "");
if (add_modes > 0) {
strcat(modebuf, "+");
if ((add_modes & CUS_OWNER) && !(status & CUS_OWNER)) {
tmp = stripModePrefix(ircd->ownerset);
if (!(status & CUS_OP)) {
anope_cmd_mode(whosends(ci), c->name, "+o%s %s %s", tmp,
user->nick, user->nick);
chan_set_user_status(c, user, CUS_OWNER | CUS_OP);
} else {
anope_cmd_mode(whosends(ci), c->name, "+%s %s", tmp,
user->nick);
chan_set_user_status(c, user, CUS_OWNER);
}
} else if (!(status & CUS_OP)) {
anope_cmd_mode(whosends(ci), c->name, "+o %s", user->nick);
chan_set_user_status(c, user, CUS_OP);
strcat(modebuf, tmp);
free(tmp);
strcat(userbuf, " ");
strcat(userbuf, user->nick);
} else {
add_modes &= ~CUS_OWNER;
}
} else if ((ircd->protect || ircd->admin)
&& check_access(user, ci, CA_AUTOPROTECT)) {
tmp = stripModePrefix(ircd->adminset);
if (!(status & CUS_PROTECT)) {
if (!(status & CUS_OP)) {
anope_cmd_mode(whosends(ci), c->name, "+o%s %s %s", tmp,
user->nick, user->nick);
chan_set_user_status(c, user, CUS_PROTECT | CUS_OP);
} else {
anope_cmd_mode(whosends(ci), c->name, "+%s %s", tmp,
user->nick);
chan_set_user_status(c, user, CUS_PROTECT);
}
} else if (!(status & CUS_OP)) {
anope_cmd_mode(whosends(ci), c->name, "+o %s", user->nick);
chan_set_user_status(c, user, CUS_OP);
if ((add_modes & CUS_PROTECT) && !(status & CUS_PROTECT)) {
tmp = stripModePrefix(ircd->adminset);
strcat(modebuf, tmp);
free(tmp);
strcat(userbuf, " ");
strcat(userbuf, user->nick);
} else {
add_modes &= ~CUS_PROTECT;
}
} else if (check_access(user, ci, CA_AUTOOP)) {
if (!(status & CUS_OP)) {
anope_cmd_mode(whosends(ci), c->name, "+o %s", user->nick);
chan_set_user_status(c, user, CUS_OP);
if ((add_modes & CUS_OP) && !(status & CUS_OP)) {
strcat(modebuf, "o");
strcat(userbuf, " ");
strcat(userbuf, user->nick);
} else {
add_modes &= ~CUS_OP;
}
} else if (ircd->halfop && check_access(user, ci, CA_AUTOHALFOP)) {
if (!(status & CUS_HALFOP)) {
anope_cmd_mode(whosends(ci), c->name, "+h %s", user->nick);
chan_set_user_status(c, user, CUS_HALFOP);
if ((add_modes & CUS_HALFOP) && !(status & CUS_HALFOP)) {
strcat(modebuf, "h");
strcat(userbuf, " ");
strcat(userbuf, user->nick);
} else {
add_modes &= ~CUS_HALFOP;
}
} else if (check_access(user, ci, CA_AUTOVOICE)) {
if (!(status & CUS_VOICE)) {
anope_cmd_mode(whosends(ci), c->name, "+v %s", user->nick);
chan_set_user_status(c, user, CUS_VOICE);
if ((add_modes & CUS_VOICE) && !(status & CUS_VOICE)) {
strcat(modebuf, "v");
strcat(userbuf, " ");
strcat(userbuf, user->nick);
} else {
add_modes &= ~CUS_VOICE;
}
}
if (rem_modes > 0) {
strcat(modebuf, "-");
if (rem_modes & CUS_OWNER) {
tmp = stripModePrefix(ircd->ownerset);
strcat(modebuf, tmp);
free(tmp);
strcat(userbuf, " ");
strcat(userbuf, user->nick);
}
if (rem_modes & CUS_PROTECT) {
tmp = stripModePrefix(ircd->adminset);
strcat(modebuf, tmp);
free(tmp);
strcat(userbuf, " ");
strcat(userbuf, user->nick);
}
if (rem_modes & CUS_OP) {
strcat(modebuf, "o");
strcat(userbuf, " ");
strcat(userbuf, user->nick);
}
if (rem_modes & CUS_HALFOP) {
strcat(modebuf, "h");
strcat(userbuf, " ");
strcat(userbuf, user->nick);
}
}
/* Here, both can be empty again due to the "isn't it set already?"
* checks above. -GD
*/
if (!add_modes && !rem_modes)
return;
anope_cmd_mode(whosends(ci), c->name, "%s%s", modebuf, userbuf);
if (add_modes > 0)
chan_set_user_status(c, user, add_modes);
if (rem_modes > 0)
chan_remove_user_status(c, user, rem_modes);
}
/*************************************************************************/
+1 -1
View File
@@ -1144,7 +1144,7 @@ char *str_signed(unsigned char *str)
**/
char *stripModePrefix(const char *str) {
if(str) {
if (str && ((*str == '+') || (*str == '-'))) {
return sstrdup(str+1);
}
return NULL;
+1 -1
View File
@@ -2683,7 +2683,7 @@ static int do_setmodes(User * u)
/* Walk users current channels */
for (uc = u->chans; uc; uc = uc->next) {
if ((c = uc->chan))
chan_set_correct_modes(u, c);
chan_set_correct_modes(u, c, 1);
}
return MOD_CONT;
}
+5 -1
View File
@@ -8,10 +8,14 @@
VERSION_MAJOR="1"
VERSION_MINOR="7"
VERSION_PATCH="8"
VERSION_BUILD="645"
VERSION_BUILD="646"
# $Log$
#
# BUILD : 1.7.8 (646)
# BUGS : 327 329 334 335
# NOTES : Fixed quite a few bugs with mode handling (not always removed correctly, added/removed modes were split), fixed a segfault in chan_set_correct_modes, fixed some issues with topic setting, made stripModePrefix really stripping the mode prefix instead of the first char
#
# BUILD : 1.7.8 (645)
# BUGS : none
# NOTES : Language file normalization.