3
0
mirror of https://github.com/ergochat/ergo.git synced 2024-11-26 05:49:25 +01:00

Merge remote-tracking branch 'origin/master' into monoffline

This commit is contained in:
Shivaram Lingamneni 2020-05-30 23:25:25 -04:00
commit aafc89feaa
12 changed files with 81 additions and 34 deletions

View File

@ -337,7 +337,6 @@ func (server *Server) RunClient(conn IRCConn) {
session.idletimer.Initialize(session) session.idletimer.Initialize(session)
session.resetFakelag() session.resetFakelag()
ApplyUserModeChanges(client, config.Accounts.defaultUserModes, false, nil)
if wConn.Secure { if wConn.Secure {
client.SetMode(modes.TLS, true) client.SetMode(modes.TLS, true)
} }

View File

@ -256,7 +256,7 @@ type AccountConfig struct {
exemptedNets []net.IPNet exemptedNets []net.IPNet
} `yaml:"require-sasl"` } `yaml:"require-sasl"`
DefaultUserModes *string `yaml:"default-user-modes"` DefaultUserModes *string `yaml:"default-user-modes"`
defaultUserModes modes.ModeChanges defaultUserModes modes.Modes
LDAP ldap.ServerConfig LDAP ldap.ServerConfig
LoginThrottling ThrottleConfig `yaml:"login-throttling"` LoginThrottling ThrottleConfig `yaml:"login-throttling"`
SkipServerPassword bool `yaml:"skip-server-password"` SkipServerPassword bool `yaml:"skip-server-password"`

View File

@ -2724,6 +2724,8 @@ func whoisHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Res
} }
clientNick := client.Nick() clientNick := client.Nick()
rb.Add(nil, client.server.name, RPL_WHOISUSER, clientNick, service.Name, service.Name, "localhost", "*", fmt.Sprintf(client.t("Network service, for more info /msg %s HELP"), service.Name)) rb.Add(nil, client.server.name, RPL_WHOISUSER, clientNick, service.Name, service.Name, "localhost", "*", fmt.Sprintf(client.t("Network service, for more info /msg %s HELP"), service.Name))
// #1080:
rb.Add(nil, client.server.name, RPL_WHOISOPERATOR, clientNick, service.Name, client.t("is a network service"))
// hehe // hehe
if client.HasMode(modes.TLS) { if client.HasMode(modes.TLS) {
rb.Add(nil, client.server.name, RPL_WHOISSECURE, clientNick, service.Name, client.t("is using a secure connection")) rb.Add(nil, client.server.name, RPL_WHOISSECURE, clientNick, service.Name, client.t("is using a secure connection"))

View File

@ -23,7 +23,7 @@ var (
// DefaultUserModes are set on all users when they login. // DefaultUserModes are set on all users when they login.
// this can be overridden in the `accounts` config, with the `default-user-modes` key // this can be overridden in the `accounts` config, with the `default-user-modes` key
DefaultUserModes = modes.ModeChanges{} DefaultUserModes = modes.Modes{}
) )
// ApplyUserModeChanges applies the given changes, and returns the applied changes. // ApplyUserModeChanges applies the given changes, and returns the applied changes.
@ -110,32 +110,35 @@ func ApplyUserModeChanges(client *Client, changes modes.ModeChanges, force bool,
return applied return applied
} }
// 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 {
modeChangeStrings := strings.Fields(rawModes)
modeChanges, _ := parser(modeChangeStrings...)
defaultModes := make(modes.Modes, 0)
for _, modeChange := range modeChanges {
if modeChange.Op == modes.Add {
defaultModes = append(defaultModes, modeChange.Mode)
}
}
return defaultModes
}
// ParseDefaultChannelModes parses the `default-modes` line of the config // ParseDefaultChannelModes parses the `default-modes` line of the config
func ParseDefaultChannelModes(rawModes *string) modes.Modes { func ParseDefaultChannelModes(rawModes *string) modes.Modes {
if rawModes == nil { if rawModes == nil {
// not present in config, fall back to compile-time default // not present in config, fall back to compile-time default
return DefaultChannelModes return DefaultChannelModes
} }
modeChangeStrings := strings.Fields(*rawModes) return parseDefaultModes(*rawModes, modes.ParseChannelModeChanges)
modeChanges, _ := modes.ParseChannelModeChanges(modeChangeStrings...)
defaultChannelModes := make(modes.Modes, 0)
for _, modeChange := range modeChanges {
if modeChange.Op == modes.Add {
defaultChannelModes = append(defaultChannelModes, modeChange.Mode)
}
}
return defaultChannelModes
} }
// ParseDefaultUserModes parses the `default-user-modes` line of the config // ParseDefaultUserModes parses the `default-user-modes` line of the config
func ParseDefaultUserModes(rawModes *string) modes.ModeChanges { func ParseDefaultUserModes(rawModes *string) modes.Modes {
if rawModes == nil { if rawModes == nil {
// not present in config, fall back to compile-time default // not present in config, fall back to compile-time default
return DefaultUserModes return DefaultUserModes
} }
modeChangeStrings := strings.Fields(*rawModes) return parseDefaultModes(*rawModes, modes.ParseUserModeChanges)
modeChanges, _ := modes.ParseUserModeChanges(modeChangeStrings...)
return modeChanges
} }
// #1021: channel key must be valid as a non-final parameter // #1021: channel key must be valid as a non-final parameter

View File

@ -6,6 +6,7 @@
package modes package modes
import ( import (
"sort"
"strings" "strings"
"github.com/oragono/oragono/irc/utils" "github.com/oragono/oragono/irc/utils"
@ -418,3 +419,27 @@ func (set *ModeSet) HighestChannelUserMode() (result Mode) {
} }
return 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))
copy(userModes, SupportedUserModes)
sort.Sort(ByCodepoint(userModes))
channelModes := make(Modes, len(SupportedChannelModes)+len(ChannelUserModes))
copy(channelModes, SupportedChannelModes)
copy(channelModes[len(SupportedChannelModes):], ChannelUserModes)
sort.Sort(ByCodepoint(channelModes))
// XXX enumerate these by hand, i can't see any way to DRY this
channelParametrizedModes := Modes{BanMask, ExceptMask, InviteMask, Key, UserLimit}
channelParametrizedModes = append(channelParametrizedModes, ChannelUserModes...)
sort.Sort(ByCodepoint(channelParametrizedModes))
return userModes.String(), channelModes.String(), channelParametrizedModes.String()
}

View File

@ -43,19 +43,19 @@ func TestParseDefaultUserModes(t *testing.T) {
var parseTests = []struct { var parseTests = []struct {
raw *string raw *string
expected modes.ModeChanges expected modes.Modes
}{ }{
{&iR, modes.ModeChanges{{Mode: modes.Invisible, Op: modes.Add}, {Mode: modes.RegisteredOnly, Op: modes.Add}}}, {&iR, modes.Modes{modes.Invisible, modes.RegisteredOnly}},
{&i, modes.ModeChanges{{Mode: modes.Invisible, Op: modes.Add}}}, {&i, modes.Modes{modes.Invisible}},
{&empty, modes.ModeChanges{}}, {&empty, modes.Modes{}},
{&rminusi, modes.ModeChanges{{Mode: modes.RegisteredOnly, Op: modes.Add}}}, {&rminusi, modes.Modes{modes.RegisteredOnly}},
{nil, modes.ModeChanges{}}, {nil, modes.Modes{}},
} }
for _, testcase := range parseTests { for _, testcase := range parseTests {
result := ParseDefaultUserModes(testcase.raw) result := ParseDefaultUserModes(testcase.raw)
if !reflect.DeepEqual(result, testcase.expected) { if !reflect.DeepEqual(result, testcase.expected) {
t.Errorf("expected modes %v, got %v", testcase.expected, result) t.Errorf("expected modes %s, got %s", testcase.expected, result)
} }
} }
} }

View File

@ -18,6 +18,9 @@ import (
var ( var (
restrictedNicknames = []string{ restrictedNicknames = []string{
"=scene=", // used for rp commands "=scene=", // used for rp commands
"Global", // global announcements on some networks
// common services not implemented by us:
"MemoServ", "BotServ", "OperServ",
} }
restrictedCasefoldedNicks = make(map[string]bool) restrictedCasefoldedNicks = make(map[string]bool)

View File

@ -36,10 +36,8 @@ var (
// common error line to sub values into // common error line to sub values into
errorMsg = "ERROR :%s\r\n" errorMsg = "ERROR :%s\r\n"
// supportedUserModesString acts as a cache for when we introduce users // three final parameters of 004 RPL_MYINFO, enumerating our supported modes
supportedUserModesString = modes.SupportedUserModes.String() rplMyInfo1, rplMyInfo2, rplMyInfo3 = modes.RplMyInfo()
// supportedChannelModesString acts as a cache for when we introduce users
supportedChannelModesString = modes.SupportedChannelModes.String()
// whitelist of caps to serve on the STS-only listener. In particular, // whitelist of caps to serve on the STS-only listener. In particular,
// never advertise SASL, to discourage people from sending their passwords: // never advertise SASL, to discourage people from sending their passwords:
@ -266,11 +264,18 @@ func (server *Server) tryRegister(c *Client, session *Session) (exiting bool) {
return true return true
} }
// Apply default user modes (without updating the invisible counter)
// The number of invisible users will be updated by server.stats.Register
// if we're using default user mode +i.
for _, defaultMode := range server.Config().Accounts.defaultUserModes {
c.SetMode(defaultMode, true)
}
// registration has succeeded: // registration has succeeded:
c.SetRegistered() c.SetRegistered()
// count new user in statistics // count new user in statistics
server.stats.Register() server.stats.Register(c.HasMode(modes.Invisible))
server.monitorManager.AlertAbout(c.Nick(), c.NickCasefolded(), true) server.monitorManager.AlertAbout(c.Nick(), c.NickCasefolded(), true)
server.playRegistrationBurst(session) server.playRegistrationBurst(session)
@ -290,8 +295,7 @@ func (server *Server) playRegistrationBurst(session *Session) {
session.Send(nil, server.name, RPL_WELCOME, d.nick, fmt.Sprintf(c.t("Welcome to the Internet Relay Network %s"), d.nick)) session.Send(nil, server.name, RPL_WELCOME, d.nick, fmt.Sprintf(c.t("Welcome to the Internet Relay Network %s"), d.nick))
session.Send(nil, server.name, RPL_YOURHOST, d.nick, fmt.Sprintf(c.t("Your host is %[1]s, running version %[2]s"), server.name, Ver)) session.Send(nil, server.name, RPL_YOURHOST, d.nick, fmt.Sprintf(c.t("Your host is %[1]s, running version %[2]s"), server.name, Ver))
session.Send(nil, server.name, RPL_CREATED, d.nick, fmt.Sprintf(c.t("This server was created %s"), server.ctime.Format(time.RFC1123))) session.Send(nil, server.name, RPL_CREATED, d.nick, fmt.Sprintf(c.t("This server was created %s"), server.ctime.Format(time.RFC1123)))
//TODO(dan): Look at adding last optional [<channel modes with a parameter>] parameter session.Send(nil, server.name, RPL_MYINFO, d.nick, server.name, Ver, rplMyInfo1, rplMyInfo2, rplMyInfo3)
session.Send(nil, server.name, RPL_MYINFO, d.nick, server.name, Ver, supportedUserModesString, supportedChannelModesString)
if c.isSTSOnly { if c.isSTSOnly {
for _, line := range server.Config().Server.STS.bannerLines { for _, line := range server.Config().Server.STS.bannerLines {

View File

@ -41,9 +41,12 @@ func (s *Stats) AddRegistered(invisible, operator bool) {
} }
// Transition a client from unregistered to registered // Transition a client from unregistered to registered
func (s *Stats) Register() { func (s *Stats) Register(invisible bool) {
s.mutex.Lock() s.mutex.Lock()
s.Unknown -= 1 s.Unknown -= 1
if invisible {
s.Invisible += 1
}
s.Total += 1 s.Total += 1
s.setMax() s.setMax()
s.mutex.Unlock() s.mutex.Unlock()

View File

@ -35,7 +35,7 @@ func ArgsToStrings(maxLength int, arguments []string, delim string) []string {
continue continue
} }
if len(buffer) > 1 { if len(buffer) > 0 {
buffer += delim buffer += delim
} }
buffer += arguments[0] buffer += arguments[0]

View File

@ -5,6 +5,14 @@ package utils
import "testing" import "testing"
func TestArgsToStrings(t *testing.T) {
val := ArgsToStrings(512, []string{"a", "b", "c"}, ",")
assertEqual(val, []string{"a,b,c"}, t)
val = ArgsToStrings(10, []string{"abcd", "efgh", "ijkl"}, ",")
assertEqual(val, []string{"abcd,efgh", "ijkl"}, t)
}
func TestStringToBool(t *testing.T) { func TestStringToBool(t *testing.T) {
val, err := StringToBool("on") val, err := StringToBool("on")
assertEqual(val, true, t) assertEqual(val, true, t)

View File

@ -235,7 +235,7 @@
"That nickname is already reserved by someone else": "Pseudonimul este rezervat de altcineva", "That nickname is already reserved by someone else": "Pseudonimul este rezervat de altcineva",
"That nickname is not registered": "Pseudonimul nu este înregistrat", "That nickname is not registered": "Pseudonimul nu este înregistrat",
"That vhost isn't being offered by the server": "Gazda virtuală nu este oferită de către server", "That vhost isn't being offered by the server": "Gazda virtuală nu este oferită de către server",
"The following vhosts are available and can be chosen with /HOSTSERV TAKE:": "", "The following vhosts are available and can be chosen with /HOSTSERV TAKE:": "Următoarele gazde virtuale sunt disponibile și pot fi alese cu comanda /HOSTSERV TAKE:",
"The server does not offer any vhosts": "Serverul nu oferă nici o gazdă virtuală", "The server does not offer any vhosts": "Serverul nu oferă nici o gazdă virtuală",
"The server does not offer any vhosts, but you can request one with /HOSTSERV REQUEST": "Serverul nu oferă nici o gazdă virtuală, actualmente. Poți cere una, cu comanda /HOSTSERV REQUEST", "The server does not offer any vhosts, but you can request one with /HOSTSERV REQUEST": "Serverul nu oferă nici o gazdă virtuală, actualmente. Poți cere una, cu comanda /HOSTSERV REQUEST",
"The stored channel history setting is: %s": "Setarea pentru stocarea istoricului mesajelor canalului este: %s", "The stored channel history setting is: %s": "Setarea pentru stocarea istoricului mesajelor canalului este: %s",
@ -317,7 +317,7 @@
"You're not logged into an account": "Nu te-ai autentificat la niciun cont", "You're not logged into an account": "Nu te-ai autentificat la niciun cont",
"You're not on that channel": "Nu te afli pe acel canal", "You're not on that channel": "Nu te afli pe acel canal",
"You're now logged in as %s": "Te-ai autentificat ca: %s", "You're now logged in as %s": "Te-ai autentificat ca: %s",
"Your account credentials are managed externally and cannot be changed here": "", "Your account credentials are managed externally and cannot be changed here": "Credențialele contului tău sunt administrate extern și nu pot fi modificate aici",
"Your account is not configured to receive autoreplayed missed messages": "Contul tău nu este configurat pentru derularea automată a mesajelor pierdute", "Your account is not configured to receive autoreplayed missed messages": "Contul tău nu este configurat pentru derularea automată a mesajelor pierdute",
"Your client does not support BRB": "Clientul folosit de tine nu suportă BRB", "Your client does not support BRB": "Clientul folosit de tine nu suportă BRB",
"Your host is %[1]s, running version %[2]s": "Gazda ta este %[1]s, rulând versiunea %[2]s", "Your host is %[1]s, running version %[2]s": "Gazda ta este %[1]s, rulând versiunea %[2]s",