From b6a8cc20c243d1ef358b8d8255fc4a6a7e7b4dea Mon Sep 17 00:00:00 2001 From: Shivaram Lingamneni Date: Wed, 29 Jan 2025 01:10:33 -0500 Subject: [PATCH 1/8] add conn ID to SASL auth logline --- irc/getters.go | 7 +++++++ irc/handlers.go | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/irc/getters.go b/irc/getters.go index d0e08256..12839710 100644 --- a/irc/getters.go +++ b/irc/getters.go @@ -223,6 +223,13 @@ func (session *Session) SetAway(awayMessage string) (wasAway, nowAway string) { return } +func (session *Session) ConnID() string { + if session == nil { + return "*" + } + return session.connID +} + func (client *Client) autoAwayEnabledNoMutex(config *Config) bool { return client.registered && client.alwaysOn && persistenceEnabled(config.Accounts.Multiclient.AutoAway, client.accountSettings.AutoAway) diff --git a/irc/handlers.go b/irc/handlers.go index 85354a3b..88890510 100644 --- a/irc/handlers.go +++ b/irc/handlers.go @@ -137,7 +137,7 @@ func sendSuccessfulAccountAuth(service *ircService, client *Client, rb *Response } } - client.server.logger.Info("accounts", "client", details.nick, "logged into account", details.accountName) + client.server.logger.Info("accounts", rb.session.ConnID(), details.nick, "logged into account", details.accountName) } func (server *Server) sendLoginSnomask(nickMask, accountName string) { From 4dfb7cc7ae3a5cbbbdc62edfde2d93a6f0697a87 Mon Sep 17 00:00:00 2001 From: Shivaram Lingamneni Date: Mon, 3 Feb 2025 20:51:08 -0500 Subject: [PATCH 2/8] use slices.Contains in irc/modes --- irc/modes/modes.go | 35 +++++++---------------------------- 1 file changed, 7 insertions(+), 28 deletions(-) diff --git a/irc/modes/modes.go b/irc/modes/modes.go index ad160169..c9483bb4 100644 --- a/irc/modes/modes.go +++ b/irc/modes/modes.go @@ -7,6 +7,7 @@ package modes import ( "fmt" + "slices" "sort" "strings" @@ -219,19 +220,11 @@ func ParseUserModeChanges(params ...string) (ModeChanges, map[rune]bool) { } } - var isKnown bool - for _, supportedMode := range SupportedUserModes { - if rune(supportedMode) == mode { - isKnown = true - break - } - } - if !isKnown { + if slices.Contains(SupportedUserModes, Mode(mode)) { + changes = append(changes, change) + } else { unknown[mode] = true - continue } - - changes = append(changes, change) } } @@ -304,25 +297,11 @@ func ParseChannelModeChanges(params ...string) (ModeChanges, map[rune]bool) { } } - var isKnown bool - for _, supportedMode := range SupportedChannelModes { - if rune(supportedMode) == mode { - isKnown = true - break - } - } - for _, supportedMode := range ChannelUserModes { - if rune(supportedMode) == mode { - isKnown = true - break - } - } - if !isKnown { + if slices.Contains(SupportedChannelModes, Mode(mode)) || slices.Contains(ChannelUserModes, Mode(mode)) { + changes = append(changes, change) + } else { unknown[mode] = true - continue } - - changes = append(changes, change) } } From 07669f9eb40bffca762e159359e46cb6a13598f1 Mon Sep 17 00:00:00 2001 From: Shivaram Lingamneni Date: Mon, 3 Feb 2025 21:13:57 -0500 Subject: [PATCH 3/8] remove hashset from mode parsing --- irc/handlers.go | 6 +++--- irc/modes.go | 2 +- irc/modes/modes.go | 14 ++++---------- irc/modes/modes_test.go | 10 ++++++---- 4 files changed, 14 insertions(+), 18 deletions(-) diff --git a/irc/handlers.go b/irc/handlers.go index 88890510..296a518b 100644 --- a/irc/handlers.go +++ b/irc/handlers.go @@ -1852,11 +1852,11 @@ func cmodeHandler(server *Server, client *Client, msg ircmsg.Message, rb *Respon if 1 < len(msg.Params) { // parse out real mode changes params := msg.Params[1:] - var unknown map[rune]bool + var unknown []rune changes, unknown = modes.ParseChannelModeChanges(params...) // alert for unknown mode changes - for char := range unknown { + for _, char := range unknown { rb.Add(nil, server.name, ERR_UNKNOWNMODE, client.nick, string(char), client.t("is an unknown mode character to me")) } if len(unknown) == 1 && len(changes) == 0 { @@ -1943,7 +1943,7 @@ func umodeHandler(server *Server, client *Client, msg ircmsg.Message, rb *Respon changes, unknown := modes.ParseUserModeChanges(params...) // alert for unknown mode changes - for char := range unknown { + for _, char := range unknown { rb.Add(nil, server.name, ERR_UNKNOWNMODE, cDetails.nick, string(char), client.t("is an unknown mode character to me")) } if len(unknown) == 1 && len(changes) == 0 { diff --git a/irc/modes.go b/irc/modes.go index e6079e24..cd7581ba 100644 --- a/irc/modes.go +++ b/irc/modes.go @@ -116,7 +116,7 @@ func ApplyUserModeChanges(client *Client, changes modes.ModeChanges, force bool, } // parseDefaultModes uses the provided mode change parser to parse the rawModes. -func parseDefaultModes(rawModes string, parser func(params ...string) (modes.ModeChanges, map[rune]bool)) modes.Modes { +func parseDefaultModes(rawModes string, parser func(params ...string) (modes.ModeChanges, []rune)) modes.Modes { modeChangeStrings := strings.Fields(rawModes) modeChanges, _ := parser(modeChangeStrings...) defaultModes := make(modes.Modes, 0) diff --git a/irc/modes/modes.go b/irc/modes/modes.go index c9483bb4..fc902ceb 100644 --- a/irc/modes/modes.go +++ b/irc/modes/modes.go @@ -190,10 +190,7 @@ func GetLowestChannelModePrefix(prefixes string) (lowest Mode) { // // ParseUserModeChanges returns the valid changes, and the list of unknown chars. -func ParseUserModeChanges(params ...string) (ModeChanges, map[rune]bool) { - changes := make(ModeChanges, 0) - unknown := make(map[rune]bool) - +func ParseUserModeChanges(params ...string) (changes ModeChanges, unknown []rune) { op := List if 0 < len(params) { @@ -223,7 +220,7 @@ func ParseUserModeChanges(params ...string) (ModeChanges, map[rune]bool) { if slices.Contains(SupportedUserModes, Mode(mode)) { changes = append(changes, change) } else { - unknown[mode] = true + unknown = append(unknown, mode) } } } @@ -232,10 +229,7 @@ func ParseUserModeChanges(params ...string) (ModeChanges, map[rune]bool) { } // ParseChannelModeChanges returns the valid changes, and the list of unknown chars. -func ParseChannelModeChanges(params ...string) (ModeChanges, map[rune]bool) { - changes := make(ModeChanges, 0) - unknown := make(map[rune]bool) - +func ParseChannelModeChanges(params ...string) (changes ModeChanges, unknown []rune) { op := List if 0 < len(params) { @@ -300,7 +294,7 @@ func ParseChannelModeChanges(params ...string) (ModeChanges, map[rune]bool) { if slices.Contains(SupportedChannelModes, Mode(mode)) || slices.Contains(ChannelUserModes, Mode(mode)) { changes = append(changes, change) } else { - unknown[mode] = true + unknown = append(unknown, mode) } } } diff --git a/irc/modes/modes_test.go b/irc/modes/modes_test.go index 67d28c2f..03f42c33 100644 --- a/irc/modes/modes_test.go +++ b/irc/modes/modes_test.go @@ -5,6 +5,7 @@ package modes import ( "reflect" + "slices" "strings" "testing" ) @@ -16,7 +17,7 @@ func assertEqual(supplied, expected interface{}, t *testing.T) { } func TestParseUserModeChanges(t *testing.T) { - emptyUnknown := make(map[rune]bool) + var emptyUnknown []rune changes, unknown := ParseUserModeChanges("+i") assertEqual(unknown, emptyUnknown, t) assertEqual(changes, ModeChanges{ModeChange{Op: Add, Mode: Invisible}}, t) @@ -48,10 +49,11 @@ func TestParseUserModeChanges(t *testing.T) { } func TestIssue874(t *testing.T) { - emptyUnknown := make(map[rune]bool) + var emptyModeChanges ModeChanges + var emptyUnknown []rune modes, unknown := ParseChannelModeChanges("+k") assertEqual(unknown, emptyUnknown, t) - assertEqual(modes, ModeChanges{}, t) + assertEqual(modes, emptyModeChanges, t) modes, unknown = ParseChannelModeChanges("+k", "beer") assertEqual(unknown, emptyUnknown, t) @@ -151,7 +153,7 @@ func TestParseChannelModeChanges(t *testing.T) { } modes, unknown = ParseChannelModeChanges("+tx") - if len(unknown) != 1 || !unknown['x'] { + if len(unknown) != 1 || !slices.Contains(unknown, 'x') { t.Errorf("expected that x is an unknown mode, instead: %v", unknown) } expected = ModeChange{ From 8fa6e19c2e15df7da84cb2bdde2487608cf0a274 Mon Sep 17 00:00:00 2001 From: Shivaram Lingamneni Date: Mon, 3 Feb 2025 21:33:50 -0500 Subject: [PATCH 4/8] fix #2213 We intended to suppress 324 and 329 when there is no valid mode change, only unknown modes. Fix these checks. --- irc/handlers.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/irc/handlers.go b/irc/handlers.go index 296a518b..3dd6ba40 100644 --- a/irc/handlers.go +++ b/irc/handlers.go @@ -1859,7 +1859,7 @@ func cmodeHandler(server *Server, client *Client, msg ircmsg.Message, rb *Respon for _, char := range unknown { rb.Add(nil, server.name, ERR_UNKNOWNMODE, client.nick, string(char), client.t("is an unknown mode character to me")) } - if len(unknown) == 1 && len(changes) == 0 { + if len(unknown) != 0 && len(changes) == 0 { return false } } @@ -1946,7 +1946,7 @@ func umodeHandler(server *Server, client *Client, msg ircmsg.Message, rb *Respon for _, char := range unknown { rb.Add(nil, server.name, ERR_UNKNOWNMODE, cDetails.nick, string(char), client.t("is an unknown mode character to me")) } - if len(unknown) == 1 && len(changes) == 0 { + if len(unknown) != 0 && len(changes) == 0 { return false } From 4851825d4f32938c84864d56898197a43e65429a Mon Sep 17 00:00:00 2001 From: Shivaram Lingamneni Date: Wed, 5 Feb 2025 00:47:23 -0500 Subject: [PATCH 5/8] use slices.SortFunc for modes --- irc/modes/modes.go | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/irc/modes/modes.go b/irc/modes/modes.go index fc902ceb..3587773c 100644 --- a/irc/modes/modes.go +++ b/irc/modes/modes.go @@ -8,7 +8,6 @@ package modes import ( "fmt" "slices" - "sort" "strings" "github.com/ergochat/ergo/irc/utils" @@ -401,28 +400,22 @@ func (set *ModeSet) HighestChannelUserMode() (result Mode) { return } -type ByCodepoint Modes - -func (a ByCodepoint) Len() int { return len(a) } -func (a ByCodepoint) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -func (a ByCodepoint) Less(i, j int) bool { return a[i] < a[j] } - func RplMyInfo() (param1, param2, param3 string) { userModes := make(Modes, len(SupportedUserModes), len(SupportedUserModes)+1) copy(userModes, SupportedUserModes) // TLS is not in SupportedUserModes because it can't be modified userModes = append(userModes, TLS) - sort.Sort(ByCodepoint(userModes)) + slices.Sort(userModes) channelModes := make(Modes, len(SupportedChannelModes)+len(ChannelUserModes)) copy(channelModes, SupportedChannelModes) copy(channelModes[len(SupportedChannelModes):], ChannelUserModes) - sort.Sort(ByCodepoint(channelModes)) + slices.Sort(channelModes) // XXX enumerate these by hand, i can't see any way to DRY this channelParametrizedModes := Modes{BanMask, ExceptMask, InviteMask, Key, UserLimit, Forward} channelParametrizedModes = append(channelParametrizedModes, ChannelUserModes...) - sort.Sort(ByCodepoint(channelParametrizedModes)) + slices.Sort(channelParametrizedModes) return userModes.String(), channelModes.String(), channelParametrizedModes.String() } @@ -438,10 +431,10 @@ func ChanmodesToken() (result string) { // type D: modes without parameters D := Modes{InviteOnly, Moderated, NoOutside, OpOnlyTopic, ChanRoleplaying, Secret, NoCTCP, RegisteredOnly, RegisteredOnlySpeak, Auditorium, OpModerated} - sort.Sort(ByCodepoint(A)) - sort.Sort(ByCodepoint(B)) - sort.Sort(ByCodepoint(C)) - sort.Sort(ByCodepoint(D)) + slices.Sort(A) + slices.Sort(B) + slices.Sort(C) + slices.Sort(D) return fmt.Sprintf("%s,%s,%s,%s", A.String(), B.String(), C.String(), D.String()) } From d1126b53ebd6285a4f64b16652d80a715bf806bb Mon Sep 17 00:00:00 2001 From: Shivaram Lingamneni Date: Wed, 5 Feb 2025 00:47:23 -0500 Subject: [PATCH 6/8] return constant strings in 004/005 --- irc/modes/modes.go | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/irc/modes/modes.go b/irc/modes/modes.go index 3587773c..5f0eb6b6 100644 --- a/irc/modes/modes.go +++ b/irc/modes/modes.go @@ -400,7 +400,17 @@ func (set *ModeSet) HighestChannelUserMode() (result Mode) { return } -func RplMyInfo() (param1, param2, param3 string) { +var ( + rplMyInfo1, rplMyInfo2, rplMyInfo3, chanmodesToken string +) + +func init() { + initRplMyInfo() + initChanmodesToken() +} + +func initRplMyInfo() { + // initialize constant strings published in initial numerics userModes := make(Modes, len(SupportedUserModes), len(SupportedUserModes)+1) copy(userModes, SupportedUserModes) // TLS is not in SupportedUserModes because it can't be modified @@ -417,10 +427,10 @@ func RplMyInfo() (param1, param2, param3 string) { channelParametrizedModes = append(channelParametrizedModes, ChannelUserModes...) slices.Sort(channelParametrizedModes) - return userModes.String(), channelModes.String(), channelParametrizedModes.String() + rplMyInfo1, rplMyInfo2, rplMyInfo3 = userModes.String(), channelModes.String(), channelParametrizedModes.String() } -func ChanmodesToken() (result string) { +func initChanmodesToken() { // https://modern.ircdocs.horse#chanmodes-parameter // type A: listable modes with parameters A := Modes{BanMask, ExceptMask, InviteMask} @@ -436,5 +446,13 @@ func ChanmodesToken() (result string) { slices.Sort(C) slices.Sort(D) - return fmt.Sprintf("%s,%s,%s,%s", A.String(), B.String(), C.String(), D.String()) + chanmodesToken = fmt.Sprintf("%s,%s,%s,%s", A.String(), B.String(), C.String(), D.String()) +} + +func RplMyInfo() (param1, param2, param3 string) { + return rplMyInfo1, rplMyInfo2, rplMyInfo3 +} + +func ChanmodesToken() (result string) { + return chanmodesToken } From a850602bccc5044e336efdec5254841d8c888ed5 Mon Sep 17 00:00:00 2001 From: Shivaram Lingamneni Date: Wed, 5 Feb 2025 00:47:23 -0500 Subject: [PATCH 7/8] refactor 005 token generation --- irc/isupport/list.go | 48 ++++++++++++++++++--------------------- irc/isupport/list_test.go | 2 +- 2 files changed, 23 insertions(+), 27 deletions(-) diff --git a/irc/isupport/list.go b/irc/isupport/list.go index 36b30d37..d54df127 100644 --- a/irc/isupport/list.go +++ b/irc/isupport/list.go @@ -5,7 +5,7 @@ package isupport import ( "fmt" - "sort" + "slices" "strings" ) @@ -58,7 +58,7 @@ func getTokenString(name string, value string) string { // GetDifference returns the difference between two token lists. func (il *List) GetDifference(newil *List) [][]string { - var outTokens sort.StringSlice + var outTokens []string // append removed tokens for name := range il.Tokens { @@ -84,7 +84,7 @@ func (il *List) GetDifference(newil *List) [][]string { outTokens = append(outTokens, token) } - sort.Sort(outTokens) + slices.Sort(outTokens) // create output list replies := make([][]string, 0) @@ -117,38 +117,34 @@ func (il *List) GetDifference(newil *List) [][]string { // RegenerateCachedReply regenerates the cached RPL_ISUPPORT reply func (il *List) RegenerateCachedReply() (err error) { - il.CachedReply = make([][]string, 0) - var length int // Length of the current cache - var cache []string // Token list cache - - // make sure we get a sorted list of tokens, needed for tests and looks nice - var tokens sort.StringSlice - for name := range il.Tokens { - tokens = append(tokens, name) - } - sort.Sort(tokens) - - for _, name := range tokens { - token := getTokenString(name, il.Tokens[name]) + var tokens []string + for name, value := range il.Tokens { + token := getTokenString(name, value) if token[0] == ':' || strings.Contains(token, " ") { err = fmt.Errorf("bad isupport token (cannot contain spaces or start with :): %s", token) continue } + tokens = append(tokens, token) + } + // make sure we get a sorted list of tokens, needed for tests and looks nice + slices.Sort(tokens) - if len(token)+length <= maxLastArgLength { - // account for the space separating tokens - if len(cache) > 0 { - length++ - } - cache = append(cache, token) - length += len(token) - } + var cache []string // Tokens in current line + var length int // Length of the current line - if len(cache) == maxParameters || len(token)+length >= maxLastArgLength { + for _, token := range tokens { + // account for the space separating tokens + if len(cache) == maxParameters || (len(token)+1)+length > maxLastArgLength { il.CachedReply = append(il.CachedReply, cache) - cache = make([]string, 0) + cache = nil length = 0 } + + if len(cache) > 0 { + length++ + } + length += len(token) + cache = append(cache, token) } if len(cache) > 0 { diff --git a/irc/isupport/list_test.go b/irc/isupport/list_test.go index 47fb72ef..2041ea17 100644 --- a/irc/isupport/list_test.go +++ b/irc/isupport/list_test.go @@ -37,7 +37,7 @@ func TestISUPPORT(t *testing.T) { } if !reflect.DeepEqual(tListLong.CachedReply, longReplies) { - t.Errorf("Multiple output replies did not match, got [%v]", longReplies) + t.Errorf("Multiple output replies did not match, got [%v]", tListLong.CachedReply) } // create first list From e1b5a05c27ea035c669387a8cb2c9faf5b88b4c2 Mon Sep 17 00:00:00 2001 From: Shivaram Lingamneni Date: Wed, 5 Feb 2025 00:47:23 -0500 Subject: [PATCH 8/8] refactor service help sorting --- irc/services.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/irc/services.go b/irc/services.go index 6b85f797..8e243f4b 100644 --- a/irc/services.go +++ b/irc/services.go @@ -7,7 +7,7 @@ import ( "bytes" "fmt" "log" - "sort" + "slices" "strings" "time" @@ -250,7 +250,7 @@ func serviceHelpHandler(service *ircService, server *Server, client *Client, par client.t("Here are the commands you can use:"), }...) // show general help - var shownHelpLines sort.StringSlice + var shownHelpLines []string var disabledCommands bool for _, commandInfo := range service.Commands { // skip commands user can't access @@ -268,13 +268,13 @@ func serviceHelpHandler(service *ircService, server *Server, client *Client, par shownHelpLines = append(shownHelpLines, " "+ircfmt.Unescape(client.t(commandInfo.helpShort))) } + // sort help lines + slices.Sort(shownHelpLines) + if disabledCommands { shownHelpLines = append(shownHelpLines, " "+client.t("... and other commands which have been disabled")) } - // sort help lines - sort.Sort(shownHelpLines) - // push out help text for _, line := range helpBannerLines { sendNotice(line)