From db23d3d138fdf2eca1c78028767715fc9068b02b Mon Sep 17 00:00:00 2001 From: Michael Poole Date: Sun, 14 Mar 2010 21:40:24 -0400 Subject: [PATCH] Fix various mode-related bugs (including SF#2964782 and SF#2966959). src/chanserv.c (cmd_mode): Use MCP_NO_APASS, and unparse the mode change for display. (chan_opt_usergreeting): Use MCP_NO_APASS here too. (chanserv_conf_read): Likewise. (chanserv_channel_read): Likewise. src/opserv.c (cmd_kick): Do not let users try to kick services. src/proto.h (MCP_NO_APASS): New flag. src/proto-p10.c (irc_user_mode_chars): Allow displaying +x. (mod_usermode): Treat +h as setting +x also. (mod_chanmode_parse): Reject +A and +U when passed MCP_NO_APASS. --- src/chanserv.c | 14 ++++++++------ src/opserv.c | 4 ++++ src/proto-p10.c | 8 +++++++- src/proto.h | 1 + 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/chanserv.c b/src/chanserv.c index a9f8ad1..421da74 100644 --- a/src/chanserv.c +++ b/src/chanserv.c @@ -4211,6 +4211,7 @@ static CHANSERV_FUNC(cmd_mode) struct userData *uData; struct mod_chanmode *change; short base_oplevel; + char fmt[MAXLEN]; if(argc < 2) { @@ -4230,7 +4231,7 @@ static CHANSERV_FUNC(cmd_mode) base_oplevel = 1; else base_oplevel = 1 + UL_OWNER - uData->access; - change = mod_chanmode_parse(channel, argv+1, argc-1, MCP_KEY_FREE|MCP_REGISTERED, base_oplevel); + change = mod_chanmode_parse(channel, argv+1, argc-1, MCP_KEY_FREE|MCP_REGISTERED|MCP_NO_APASS, base_oplevel); if(!change) { reply("MSG_INVALID_MODES", unsplit_string(argv+1, argc-1, NULL)); @@ -4247,8 +4248,9 @@ static CHANSERV_FUNC(cmd_mode) } modcmd_chanmode_announce(change); + mod_chanmode_format(change, fmt); mod_chanmode_free(change); - reply("CSMSG_MODES_SET", unsplit_string(argv+1, argc-1, NULL)); + reply("CSMSG_MODES_SET", fmt); return 1; } @@ -5407,7 +5409,7 @@ static MODCMD_FUNC(chan_opt_usergreeting) static MODCMD_FUNC(chan_opt_modes) { struct mod_chanmode *new_modes; - char modes[MODELEN]; + char modes[MAXLEN]; if(argc > 1) { @@ -5420,7 +5422,7 @@ static MODCMD_FUNC(chan_opt_modes) { memset(&channel->channel_info->modes, 0, sizeof(channel->channel_info->modes)); } - else if(!(new_modes = mod_chanmode_parse(channel, argv+1, argc-1, MCP_KEY_FREE|MCP_REGISTERED, 0))) + else if(!(new_modes = mod_chanmode_parse(channel, argv+1, argc-1, MCP_KEY_FREE|MCP_REGISTERED|MCP_NO_APASS, 0))) { reply("CSMSG_INVALID_MODE_LOCK", unsplit_string(argv+1, argc-1, NULL)); return 0; @@ -7057,7 +7059,7 @@ chanserv_conf_read(void) str = "+nt"; safestrncpy(mode_line, str, sizeof(mode_line)); ii = split_line(mode_line, 0, ArrayLength(modes), modes); - if((change = mod_chanmode_parse(NULL, modes, ii, MCP_KEY_FREE, 0)) + if((change = mod_chanmode_parse(NULL, modes, ii, MCP_KEY_FREE|MCP_NO_APASS, 0)) && (change->argc < 2)) { chanserv_conf.default_modes = *change; @@ -7424,7 +7426,7 @@ chanserv_channel_read(const char *key, struct record_data *hir) if(!IsSuspended(cData) && (str = database_get_data(channel, KEY_MODES, RECDB_QSTRING)) && (argc = split_line(str, 0, ArrayLength(argv), argv)) - && (modes = mod_chanmode_parse(cNode, argv, argc, MCP_KEY_FREE, 0))) { + && (modes = mod_chanmode_parse(cNode, argv, argc, MCP_KEY_FREE|MCP_NO_APASS, 0))) { cData->modes = *modes; if(off_channel > 0) cData->modes.modes_set |= MODE_REGISTERED; diff --git a/src/opserv.c b/src/opserv.c index f9af6bb..d7bddd5 100644 --- a/src/opserv.c +++ b/src/opserv.c @@ -1022,6 +1022,10 @@ static MODCMD_FUNC(cmd_kick) reply("OSMSG_NOT_ON_CHANNEL", target->nick, channel->name); return 0; } + if (IsService(target)) { + reply("MSG_SERVICE_IMMUNE", target->nick); + return 0; + } KickChannelUser(target, channel, cmd->parent->bot, reason); return 1; } diff --git a/src/proto-p10.c b/src/proto-p10.c index 6509fab..3d291a5 100644 --- a/src/proto-p10.c +++ b/src/proto-p10.c @@ -294,7 +294,7 @@ static const char *his_servercomment; static struct channelList dead_channels; /* These correspond to 1 << X: 012345678901234567 */ -const char irc_user_mode_chars[] = "o iw dkgn I"; +const char irc_user_mode_chars[] = "o iw dkgn x I"; static struct userNode *AddUser(struct server* uplink, const char *nick, const char *ident, const char *hostname, const char *modes, const char *numeric, const char *userinfo, unsigned long timestamp, const char *realip); @@ -2322,6 +2322,7 @@ void mod_usermode(struct userNode *user, const char *mode_change) { char mask[MAXLEN]; char *host, *ident; unsigned int ii; + for (ii=0; (*word != ' ') && (*word != '\0'); ) mask[ii++] = *word++; mask[ii] = 0; @@ -2335,6 +2336,7 @@ void mod_usermode(struct userNode *user, const char *mode_change) { ident = NULL; host = mask; } + user->modes |= FLAGS_HIDDEN_HOST; assign_fakehost(user, host, ident, 0, 0); } break; @@ -2431,6 +2433,8 @@ mod_chanmode_parse(struct chanNode *channel, char **modes, unsigned int argc, un } break; case 'U': + if (flags & MCP_NO_APASS) + goto error; if (add) { if ((in_arg >= argc) @@ -2447,6 +2451,8 @@ mod_chanmode_parse(struct chanNode *channel, char **modes, unsigned int argc, un } break; case 'A': + if (flags & MCP_NO_APASS) + goto error; if (add) { if ((in_arg >= argc) || keyncpy(change->new_apass, modes[in_arg++], sizeof(change->new_apass))) diff --git a/src/proto.h b/src/proto.h index 3d8e2e7..99ca109 100644 --- a/src/proto.h +++ b/src/proto.h @@ -210,6 +210,7 @@ struct mod_chanmode { #define MCP_REGISTERED 0x0008 /* chan is already registered; do not allow changes to MODE_REGISTERED */ #define MCP_UPASS_FREE 0x0010 /* -U without a key argument */ #define MCP_APASS_FREE 0x0020 /* -A without a key argument */ +#define MCP_NO_APASS 0x0040 /* Do not allow +/-A or +/-U */ #define MC_ANNOUNCE 0x0100 /* send a mod_chanmode() change out */ #define MC_NOTIFY 0x0200 /* make local callbacks to announce */ #ifdef NDEBUG -- 2.20.1