From 438fffab99e2712c954ecda49c0c87694f7e8af3 Mon Sep 17 00:00:00 2001 From: Shivaram Lingamneni Date: Fri, 21 Feb 2020 06:10:35 -0500 Subject: [PATCH] fix #725 --- irc/commands.go | 5 +++++ irc/handlers.go | 46 ++++++++++++++++++++++++++++++---------------- irc/help.go | 6 ++++++ irc/modes.go | 13 +++++++++++++ 4 files changed, 54 insertions(+), 16 deletions(-) diff --git a/irc/commands.go b/irc/commands.go index 859636b8..7a6a65fb 100644 --- a/irc/commands.go +++ b/irc/commands.go @@ -116,6 +116,11 @@ func init() { minParams: 1, oper: true, }, + "DEOPER": { + handler: deoperHandler, + minParams: 0, + oper: true, + }, "DLINE": { handler: dlineHandler, minParams: 1, diff --git a/irc/handlers.go b/irc/handlers.go index 8f3827b9..f5999daa 100644 --- a/irc/handlers.go +++ b/irc/handlers.go @@ -2141,35 +2141,49 @@ func operHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp return false } -// applies operator status to a client, who MUST NOT already be an operator +// adds or removes operator status +// XXX: to add oper, this calls into ApplyUserModeChanges, but to remove oper, +// ApplyUserModeChanges calls into this, because the commands are asymmetric +// (/OPER to add, /MODE self -o to remove) func applyOper(client *Client, oper *Oper, rb *ResponseBuffer) { details := client.Details() - oldNickmask := details.nickMask client.SetOper(oper) - newNickmask := client.NickMaskString() - if newNickmask != oldNickmask { - client.sendChghost(oldNickmask, oper.Vhost) + newDetails := client.Details() + if details.nickMask != newDetails.nickMask { + client.sendChghost(details.nickMask, newDetails.hostname) } - // set new modes: modes.Operator, plus anything specified in the config - modeChanges := make([]modes.ModeChange, len(oper.Modes)+1) - modeChanges[0] = modes.ModeChange{ - Mode: modes.Operator, - Op: modes.Add, + if oper != nil { + // set new modes: modes.Operator, plus anything specified in the config + modeChanges := make([]modes.ModeChange, len(oper.Modes)+1) + modeChanges[0] = modes.ModeChange{ + Mode: modes.Operator, + Op: modes.Add, + } + copy(modeChanges[1:], oper.Modes) + applied := ApplyUserModeChanges(client, modeChanges, true) + + client.server.snomasks.Send(sno.LocalOpers, fmt.Sprintf(ircfmt.Unescape("Client opered up $c[grey][$r%s$c[grey], $r%s$c[grey]]"), newDetails.nickMask, oper.Name)) + + rb.Broadcast(nil, client.server.name, RPL_YOUREOPER, details.nick, client.t("You are now an IRC operator")) + rb.Broadcast(nil, client.server.name, "MODE", details.nick, applied.String()) + } else { + client.server.snomasks.Send(sno.LocalOpers, fmt.Sprintf(ircfmt.Unescape("Client deopered $c[grey][$r%s$c[grey]]"), newDetails.nickMask)) } - copy(modeChanges[1:], oper.Modes) - applied := ApplyUserModeChanges(client, modeChanges, true) - client.server.snomasks.Send(sno.LocalOpers, fmt.Sprintf(ircfmt.Unescape("Client opered up $c[grey][$r%s$c[grey], $r%s$c[grey]]"), client.nickMaskString, oper.Name)) - - rb.Broadcast(nil, client.server.name, RPL_YOUREOPER, details.nick, client.t("You are now an IRC operator")) - rb.Broadcast(nil, client.server.name, "MODE", details.nick, applied.String()) for _, session := range client.Sessions() { // client may now be unthrottled by the fakelag system session.resetFakelag() } } +// DEOPER +func deoperHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool { + // pretend they sent /MODE $nick -o + fakeModeMsg := ircmsg.MakeMessage(nil, "", "MODE", client.Nick(), "-o") + return umodeHandler(server, client, fakeModeMsg, rb) +} + // PART {,} [] func partHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool { channels := strings.Split(msg.Params[0], ",") diff --git a/irc/help.go b/irc/help.go index 4f0a19da..abcce6de 100644 --- a/irc/help.go +++ b/irc/help.go @@ -160,6 +160,12 @@ Prints debug information about the IRCd.