mirror of
https://github.com/jeremyd/ergo.git
synced 2026-07-13 11:28:10 -07:00
Merge remote-tracking branch 'origin/master' into websockets_draft.2
This commit is contained in:
@@ -1174,7 +1174,12 @@ func (am *AccountManager) Unregister(account string, erase bool) error {
|
||||
var channelsStr string
|
||||
keepProtections := false
|
||||
am.server.store.Update(func(tx *buntdb.Tx) error {
|
||||
// get the unfolded account name; for an active account, this is
|
||||
// stored under accountNameKey, for an unregistered account under unregisteredKey
|
||||
accountName, _ = tx.Get(accountNameKey)
|
||||
if accountName == "" {
|
||||
accountName, _ = tx.Get(unregisteredKey)
|
||||
}
|
||||
if erase {
|
||||
tx.Delete(unregisteredKey)
|
||||
} else {
|
||||
|
||||
+48
-12
@@ -541,10 +541,16 @@ func (channel *Channel) ClientPrefixes(client *Client, isMultiPrefix bool) strin
|
||||
|
||||
func (channel *Channel) ClientHasPrivsOver(client *Client, target *Client) bool {
|
||||
channel.stateMutex.RLock()
|
||||
founder := channel.registeredFounder
|
||||
clientModes := channel.members[client]
|
||||
targetModes := channel.members[target]
|
||||
channel.stateMutex.RUnlock()
|
||||
|
||||
if founder != "" && founder == client.Account() {
|
||||
// #950: founder can kick or whatever without actually having the +q mode
|
||||
return true
|
||||
}
|
||||
|
||||
return channelUserModeHasPrivsOver(clientModes.HighestChannelUserMode(), targetModes.HighestChannelUserMode())
|
||||
}
|
||||
|
||||
@@ -1064,6 +1070,25 @@ func (channel *Channel) replayHistoryItems(rb *ResponseBuffer, items []history.I
|
||||
message := fmt.Sprintf(client.t("%[1]s changed nick to %[2]s"), nick, item.Params[0])
|
||||
rb.AddFromClient(item.Message.Time, utils.MungeSecretToken(item.Message.Msgid), histServMask, "*", nil, "PRIVMSG", chname, message)
|
||||
}
|
||||
case history.Topic:
|
||||
if eventPlayback {
|
||||
rb.AddFromClient(item.Message.Time, item.Message.Msgid, item.Nick, item.AccountName, nil, "TOPIC", chname, item.Message.Message)
|
||||
} else {
|
||||
message := fmt.Sprintf(client.t("%[1]s set the channel topic to: %[2]s"), nick, item.Message.Message)
|
||||
rb.AddFromClient(item.Message.Time, utils.MungeSecretToken(item.Message.Msgid), histServMask, "*", nil, "PRIVMSG", chname, message)
|
||||
}
|
||||
case history.Mode:
|
||||
params := make([]string, len(item.Message.Split)+1)
|
||||
params[0] = chname
|
||||
for i, pair := range item.Message.Split {
|
||||
params[i+1] = pair.Message
|
||||
}
|
||||
if eventPlayback {
|
||||
rb.AddFromClient(item.Message.Time, item.Message.Msgid, item.Nick, item.AccountName, nil, "MODE", params...)
|
||||
} else {
|
||||
message := fmt.Sprintf(client.t("%[1]s set channel modes: %[2]s"), nick, strings.Join(params[1:], " "))
|
||||
rb.AddFromClient(item.Message.Time, utils.MungeSecretToken(item.Message.Msgid), histServMask, "*", nil, "PRIVMSG", chname, message)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1113,22 +1138,30 @@ func (channel *Channel) SetTopic(client *Client, topic string, rb *ResponseBuffe
|
||||
}
|
||||
|
||||
channel.stateMutex.Lock()
|
||||
chname := channel.name
|
||||
channel.topic = topic
|
||||
channel.topicSetBy = client.nickMaskString
|
||||
channel.topicSetTime = time.Now().UTC()
|
||||
channel.stateMutex.Unlock()
|
||||
|
||||
prefix := client.NickMaskString()
|
||||
details := client.Details()
|
||||
message := utils.MakeMessage(topic)
|
||||
rb.AddFromClient(message.Time, message.Msgid, details.nickMask, details.accountName, nil, "TOPIC", chname, topic)
|
||||
for _, member := range channel.Members() {
|
||||
for _, session := range member.Sessions() {
|
||||
if session == rb.session {
|
||||
rb.Add(nil, prefix, "TOPIC", channel.name, topic)
|
||||
} else {
|
||||
session.Send(nil, prefix, "TOPIC", channel.name, topic)
|
||||
if session != rb.session {
|
||||
session.sendFromClientInternal(false, message.Time, message.Msgid, details.nickMask, details.accountName, nil, "TOPIC", chname, topic)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
channel.AddHistoryItem(history.Item{
|
||||
Type: history.Topic,
|
||||
Nick: details.nickMask,
|
||||
AccountName: details.accountName,
|
||||
Message: message,
|
||||
})
|
||||
|
||||
channel.MarkDirty(IncludeTopic)
|
||||
}
|
||||
|
||||
@@ -1251,13 +1284,16 @@ func (channel *Channel) SendSplitMessage(command string, minPrefixMode modes.Mod
|
||||
}
|
||||
}
|
||||
|
||||
channel.AddHistoryItem(history.Item{
|
||||
Type: histType,
|
||||
Message: message,
|
||||
Nick: nickmask,
|
||||
AccountName: account,
|
||||
Tags: clientOnlyTags,
|
||||
})
|
||||
// #959: don't save STATUSMSG
|
||||
if minPrefixMode == modes.Mode(0) {
|
||||
channel.AddHistoryItem(history.Item{
|
||||
Type: histType,
|
||||
Message: message,
|
||||
Nick: nickmask,
|
||||
AccountName: account,
|
||||
Tags: clientOnlyTags,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (channel *Channel) applyModeToMember(client *Client, change modes.ModeChange, rb *ResponseBuffer) (applied bool, result modes.ModeChange) {
|
||||
|
||||
+3
-3
@@ -244,7 +244,7 @@ func csAmodeHandler(server *Server, client *Client, command string, params []str
|
||||
if member.Account() == change.Arg {
|
||||
applied, change := channel.applyModeToMember(client, change, rb)
|
||||
if applied {
|
||||
announceCmodeChanges(channel, modes.ModeChanges{change}, chanservMask, rb)
|
||||
announceCmodeChanges(channel, modes.ModeChanges{change}, chanservMask, "*", rb)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -291,7 +291,7 @@ func csOpHandler(server *Server, client *Client, command string, params []string
|
||||
},
|
||||
rb)
|
||||
if applied {
|
||||
announceCmodeChanges(channelInfo, modes.ModeChanges{change}, chanservMask, rb)
|
||||
announceCmodeChanges(channelInfo, modes.ModeChanges{change}, chanservMask, "*", rb)
|
||||
}
|
||||
|
||||
csNotice(rb, fmt.Sprintf(client.t("Successfully op'd in channel %s"), channelName))
|
||||
@@ -343,7 +343,7 @@ func csRegisterHandler(server *Server, client *Client, command string, params []
|
||||
},
|
||||
rb)
|
||||
if applied {
|
||||
announceCmodeChanges(channelInfo, modes.ModeChanges{change}, chanservMask, rb)
|
||||
announceCmodeChanges(channelInfo, modes.ModeChanges{change}, chanservMask, "*", rb)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -318,6 +318,10 @@ func (server *Server) RunClient(conn clientConn, proxyLine string) {
|
||||
session.idletimer.Initialize(session)
|
||||
session.resetFakelag()
|
||||
|
||||
for _, defaultMode := range config.Accounts.defaultUserModes {
|
||||
client.SetMode(defaultMode, true)
|
||||
}
|
||||
|
||||
if conn.Config.TLSConfig != nil {
|
||||
client.SetMode(modes.TLS, true)
|
||||
// error is not useful to us here anyways so we can ignore it
|
||||
@@ -371,6 +375,10 @@ func (server *Server) AddAlwaysOnClient(account ClientAccount, chnames []string,
|
||||
alwaysOn: true,
|
||||
}
|
||||
|
||||
for _, defaultMode := range config.Accounts.defaultUserModes {
|
||||
client.SetMode(defaultMode, true)
|
||||
}
|
||||
|
||||
client.SetMode(modes.TLS, true)
|
||||
client.writerSemaphore.Initialize(1)
|
||||
client.history.Initialize(0, 0)
|
||||
|
||||
@@ -205,9 +205,18 @@ func (clients *ClientManager) SetNick(client *Client, session *Session, newNick
|
||||
// the client may just be changing case
|
||||
if currentClient != nil && currentClient != client && session != nil {
|
||||
// these conditions forbid reattaching to an existing session:
|
||||
if registered || !bouncerAllowed || account == "" || account != currentClient.Account() || client.HasMode(modes.TLS) != currentClient.HasMode(modes.TLS) {
|
||||
if registered || !bouncerAllowed || account == "" || account != currentClient.Account() {
|
||||
return "", errNicknameInUse
|
||||
}
|
||||
// check TLS modes
|
||||
if client.HasMode(modes.TLS) != currentClient.HasMode(modes.TLS) {
|
||||
if useAccountName {
|
||||
// #955: this is fatal because they can't fix it by trying a different nick
|
||||
return "", errInsecureReattach
|
||||
} else {
|
||||
return "", errNicknameInUse
|
||||
}
|
||||
}
|
||||
reattachSuccessful, numSessions, lastSeen := currentClient.AddSession(session)
|
||||
if !reattachSuccessful {
|
||||
return "", errNicknameInUse
|
||||
|
||||
@@ -263,6 +263,8 @@ type AccountConfig struct {
|
||||
Exempted []string
|
||||
exemptedNets []net.IPNet
|
||||
} `yaml:"require-sasl"`
|
||||
DefaultUserModes *string `yaml:"default-user-modes"`
|
||||
defaultUserModes modes.Modes
|
||||
LDAP ldap.ServerConfig
|
||||
LoginThrottling ThrottleConfig `yaml:"login-throttling"`
|
||||
SkipServerPassword bool `yaml:"skip-server-password"`
|
||||
@@ -552,6 +554,7 @@ type Config struct {
|
||||
OperatorOnly bool `yaml:"operator-only"`
|
||||
MaxChannelsPerAccount int `yaml:"max-channels-per-account"`
|
||||
}
|
||||
ListDelay time.Duration `yaml:"list-delay"`
|
||||
}
|
||||
|
||||
OperClasses map[string]*OperClassConfig `yaml:"oper-classes"`
|
||||
@@ -984,6 +987,8 @@ func LoadConfig(filename string) (config *Config, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
config.Accounts.defaultUserModes = ParseDefaultUserModes(config.Accounts.DefaultUserModes)
|
||||
|
||||
config.Accounts.RequireSasl.exemptedNets, err = utils.ParseNetList(config.Accounts.RequireSasl.Exempted)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Could not parse require-sasl exempted nets: %v", err.Error())
|
||||
|
||||
@@ -42,6 +42,7 @@ var (
|
||||
errNickMissing = errors.New("nick missing")
|
||||
errNicknameInvalid = errors.New("invalid nickname")
|
||||
errNicknameInUse = errors.New("nickname in use")
|
||||
errInsecureReattach = errors.New("insecure reattach")
|
||||
errNicknameReserved = errors.New("nickname is reserved")
|
||||
errNickAccountMismatch = errors.New(`Your nickname must match your account name; try logging out and logging back in with SASL`)
|
||||
errNoExistingBan = errors.New("Ban does not exist")
|
||||
|
||||
+40
-11
@@ -1408,6 +1408,14 @@ func languageHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *
|
||||
|
||||
// LIST [<channel>{,<channel>}] [<elistcond>{,<elistcond>}]
|
||||
func listHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
|
||||
config := server.Config()
|
||||
if time.Since(client.ctime) < config.Channels.ListDelay && client.Account() == "" && !client.HasMode(modes.Operator) {
|
||||
remaining := time.Until(client.ctime.Add(config.Channels.ListDelay))
|
||||
csNotice(rb, fmt.Sprintf(client.t("This server requires that you wait %v after connecting before you can use /LIST. You have %v left."), config.Channels.ListDelay, remaining))
|
||||
rb.Add(nil, server.name, RPL_LISTEND, client.Nick(), client.t("End of LIST"))
|
||||
return false
|
||||
}
|
||||
|
||||
// get channels
|
||||
var channels []string
|
||||
for _, param := range msg.Params {
|
||||
@@ -1520,24 +1528,35 @@ func cmodeHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Res
|
||||
}
|
||||
// process mode changes, include list operations (an empty set of changes does a list)
|
||||
applied := channel.ApplyChannelModeChanges(client, msg.Command == "SAMODE", changes, rb)
|
||||
announceCmodeChanges(channel, applied, client.NickMaskString(), rb)
|
||||
details := client.Details()
|
||||
announceCmodeChanges(channel, applied, details.nickMask, details.accountName, rb)
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func announceCmodeChanges(channel *Channel, applied modes.ModeChanges, source string, rb *ResponseBuffer) {
|
||||
func announceCmodeChanges(channel *Channel, applied modes.ModeChanges, source, accountName string, rb *ResponseBuffer) {
|
||||
// send out changes
|
||||
if len(applied) > 0 {
|
||||
//TODO(dan): we should change the name of String and make it return a slice here
|
||||
args := append([]string{channel.name}, applied.Strings()...)
|
||||
rb.Add(nil, source, "MODE", args...)
|
||||
message := utils.MakeMessage("")
|
||||
changeStrings := applied.Strings()
|
||||
for _, changeString := range changeStrings {
|
||||
message.Split = append(message.Split, utils.MessagePair{Message: changeString})
|
||||
}
|
||||
args := append([]string{channel.name}, changeStrings...)
|
||||
rb.AddFromClient(message.Time, message.Msgid, source, accountName, nil, "MODE", args...)
|
||||
for _, member := range channel.Members() {
|
||||
for _, session := range member.Sessions() {
|
||||
if session != rb.session {
|
||||
session.Send(nil, source, "MODE", args...)
|
||||
session.sendFromClientInternal(false, message.Time, message.Msgid, source, accountName, nil, "MODE", args...)
|
||||
}
|
||||
}
|
||||
}
|
||||
channel.AddHistoryItem(history.Item{
|
||||
Type: history.Mode,
|
||||
Nick: source,
|
||||
AccountName: accountName,
|
||||
Message: message,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2054,7 +2073,7 @@ func operHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
|
||||
}
|
||||
|
||||
// must pass at least one check, and all enabled checks
|
||||
var checkPassed, checkFailed bool
|
||||
var checkPassed, checkFailed, passwordFailed bool
|
||||
oper := server.GetOperator(msg.Params[0])
|
||||
if oper != nil {
|
||||
if oper.Fingerprint != "" {
|
||||
@@ -2065,8 +2084,11 @@ func operHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
|
||||
}
|
||||
}
|
||||
if !checkFailed && oper.Pass != nil {
|
||||
if len(msg.Params) == 1 || bcrypt.CompareHashAndPassword(oper.Pass, []byte(msg.Params[1])) != nil {
|
||||
if len(msg.Params) == 1 {
|
||||
checkFailed = true
|
||||
} else if bcrypt.CompareHashAndPassword(oper.Pass, []byte(msg.Params[1])) != nil {
|
||||
checkFailed = true
|
||||
passwordFailed = true
|
||||
} else {
|
||||
checkPassed = true
|
||||
}
|
||||
@@ -2075,11 +2097,18 @@ func operHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
|
||||
|
||||
if !checkPassed || checkFailed {
|
||||
rb.Add(nil, server.name, ERR_PASSWDMISMATCH, client.Nick(), client.t("Password incorrect"))
|
||||
client.Quit(client.t("Password incorrect"), rb.session)
|
||||
return true
|
||||
// #951: only disconnect them if we actually tried to check a password for them
|
||||
if passwordFailed {
|
||||
client.Quit(client.t("Password incorrect"), rb.session)
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
applyOper(client, oper, rb)
|
||||
if oper != nil {
|
||||
applyOper(client, oper, rb)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ const (
|
||||
Mode
|
||||
Tagmsg
|
||||
Nick
|
||||
Topic
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
+26
-8
@@ -20,6 +20,10 @@ var (
|
||||
DefaultChannelModes = modes.Modes{
|
||||
modes.NoOutside, modes.OpOnlyTopic,
|
||||
}
|
||||
|
||||
// DefaultUserModes are set on all users when they login.
|
||||
// this can be overridden in the `accounts` config, with the `default-user-modes` key
|
||||
DefaultUserModes = modes.Modes{}
|
||||
)
|
||||
|
||||
// ApplyUserModeChanges applies the given changes, and returns the applied changes.
|
||||
@@ -102,21 +106,35 @@ func ApplyUserModeChanges(client *Client, changes modes.ModeChanges, force bool,
|
||||
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
|
||||
func ParseDefaultChannelModes(rawModes *string) modes.Modes {
|
||||
if rawModes == nil {
|
||||
// not present in config, fall back to compile-time default
|
||||
return DefaultChannelModes
|
||||
}
|
||||
modeChangeStrings := strings.Fields(*rawModes)
|
||||
modeChanges, _ := modes.ParseChannelModeChanges(modeChangeStrings...)
|
||||
defaultChannelModes := make(modes.Modes, 0)
|
||||
for _, modeChange := range modeChanges {
|
||||
if modeChange.Op == modes.Add {
|
||||
defaultChannelModes = append(defaultChannelModes, modeChange.Mode)
|
||||
}
|
||||
return parseDefaultModes(*rawModes, modes.ParseChannelModeChanges)
|
||||
}
|
||||
|
||||
// ParseDefaultUserModes parses the `default-user-modes` line of the config
|
||||
func ParseDefaultUserModes(rawModes *string) modes.Modes {
|
||||
if rawModes == nil {
|
||||
// not present in config, fall back to compile-time default
|
||||
return DefaultUserModes
|
||||
}
|
||||
return defaultChannelModes
|
||||
return parseDefaultModes(*rawModes, modes.ParseUserModeChanges)
|
||||
}
|
||||
|
||||
// ApplyChannelModeChanges applies a given set of mode changes.
|
||||
|
||||
@@ -35,6 +35,31 @@ func TestParseDefaultChannelModes(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseDefaultUserModes(t *testing.T) {
|
||||
iR := "+iR"
|
||||
i := "+i"
|
||||
empty := ""
|
||||
rminusi := "+R -i"
|
||||
|
||||
var parseTests = []struct {
|
||||
raw *string
|
||||
expected modes.Modes
|
||||
}{
|
||||
{&iR, modes.Modes{modes.Invisible, modes.RegisteredOnly}},
|
||||
{&i, modes.Modes{modes.Invisible}},
|
||||
{&empty, modes.Modes{}},
|
||||
{&rminusi, modes.Modes{modes.RegisteredOnly}},
|
||||
{nil, modes.Modes{}},
|
||||
}
|
||||
|
||||
for _, testcase := range parseTests {
|
||||
result := ParseDefaultUserModes(testcase.raw)
|
||||
if !reflect.DeepEqual(result, testcase.expected) {
|
||||
t.Errorf("expected modes %s, got %s", testcase.expected, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUmodeGreaterThan(t *testing.T) {
|
||||
if !umodeGreaterThan(modes.Halfop, modes.Voice) {
|
||||
t.Errorf("expected Halfop > Voice")
|
||||
|
||||
+5
-6
@@ -25,12 +25,11 @@ var (
|
||||
restrictedSkeletons = make(map[string]bool)
|
||||
)
|
||||
|
||||
// returns whether the change succeeded or failed
|
||||
func performNickChange(server *Server, client *Client, target *Client, session *Session, nickname string, rb *ResponseBuffer) bool {
|
||||
func performNickChange(server *Server, client *Client, target *Client, session *Session, nickname string, rb *ResponseBuffer) error {
|
||||
currentNick := client.Nick()
|
||||
details := target.Details()
|
||||
if details.nick == nickname {
|
||||
return true
|
||||
return nil
|
||||
}
|
||||
hadNick := details.nick != "*"
|
||||
origNickMask := details.nickMask
|
||||
@@ -52,7 +51,7 @@ func performNickChange(server *Server, client *Client, target *Client, session *
|
||||
rb.Add(nil, server.name, ERR_UNKNOWNERROR, currentNick, "NICK", fmt.Sprintf(client.t("Could not set or change nickname: %s"), err.Error()))
|
||||
}
|
||||
if err != nil {
|
||||
return false
|
||||
return err
|
||||
}
|
||||
|
||||
message := utils.MakeMessage("")
|
||||
@@ -88,7 +87,7 @@ func performNickChange(server *Server, client *Client, target *Client, session *
|
||||
client.server.monitorManager.AlertAbout(target, true)
|
||||
target.nickTimer.Touch(rb)
|
||||
} // else: these will be deferred to the end of registration (see #572)
|
||||
return true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (server *Server) RandomlyRename(client *Client) {
|
||||
@@ -124,7 +123,7 @@ func fixupNickEqualsAccount(client *Client, rb *ResponseBuffer, config *Config)
|
||||
if !client.registered {
|
||||
return true
|
||||
}
|
||||
if !performNickChange(client.server, client, client, rb.session, client.AccountName(), rb) {
|
||||
if performNickChange(client.server, client, client, rb.session, client.AccountName(), rb) != nil {
|
||||
client.server.accounts.Logout(client)
|
||||
nsNotice(rb, client.t("A client is already using that account; try logging out and logging back in with SASL"))
|
||||
return false
|
||||
|
||||
@@ -841,6 +841,8 @@ func nsUnregisterHandler(server *Server, client *Client, command string, params
|
||||
if erase {
|
||||
// account may not be in a loadable state, e.g., if it was unregistered
|
||||
accountName = username
|
||||
// make the confirmation code nondeterministic for ERASE
|
||||
registeredAt = server.ctime
|
||||
} else {
|
||||
account, err := server.accounts.LoadAccount(username)
|
||||
if err == errAccountDoesNotExist {
|
||||
|
||||
+7
-4
@@ -438,11 +438,14 @@ func (server *Server) tryRegister(c *Client, session *Session) (exiting bool) {
|
||||
}
|
||||
|
||||
rb := NewResponseBuffer(session)
|
||||
nickAssigned := performNickChange(server, c, c, session, c.preregNick, rb)
|
||||
nickError := performNickChange(server, c, c, session, c.preregNick, rb)
|
||||
rb.Send(true)
|
||||
if !nickAssigned {
|
||||
if nickError == errInsecureReattach {
|
||||
c.Quit(c.t("You can't mix secure and insecure connections to this account"), nil)
|
||||
return true
|
||||
} else if nickError != nil {
|
||||
c.preregNick = ""
|
||||
return
|
||||
return false
|
||||
}
|
||||
|
||||
if session.client != c {
|
||||
@@ -450,7 +453,7 @@ func (server *Server) tryRegister(c *Client, session *Session) (exiting bool) {
|
||||
// we'll play the reg burst later, on the new goroutine associated with
|
||||
// (thisSession, otherClient). This is to avoid having to transfer state
|
||||
// like nickname, hostname, etc. to show the correct values in the reg burst.
|
||||
return
|
||||
return false
|
||||
}
|
||||
|
||||
// check KLINEs
|
||||
|
||||
Reference in New Issue
Block a user