3
0
mirror of https://github.com/ergochat/ergo.git synced 2024-11-14 07:59:31 +01:00

fix critical bugs in RENAME

Channel rename (both of registered and unregistered channels) would leave
the old name unreclaimable.
This commit is contained in:
Shivaram Lingamneni 2020-12-14 23:01:41 -05:00
parent 0d1521d4c4
commit cc2b6d27a0
2 changed files with 39 additions and 29 deletions

View File

@ -106,7 +106,7 @@ func (cm *ChannelManager) Join(client *Client, name string, key string, isSajoin
return nil, errInsufficientPrivs return nil, errInsufficientPrivs
} }
// enforce confusables // enforce confusables
if cm.chansSkeletons.Has(skeleton) || (!registered && cm.registeredSkeletons.Has(skeleton)) { if !registered && (cm.chansSkeletons.Has(skeleton) || cm.registeredSkeletons.Has(skeleton)) {
return nil, errConfusableIdentifier return nil, errConfusableIdentifier
} }
entry = &channelManagerEntry{ entry = &channelManagerEntry{
@ -219,10 +219,13 @@ func (cm *ChannelManager) SetRegistered(channelName string, account string) (err
if err != nil { if err != nil {
return err return err
} }
// transfer the skeleton from chansSkeletons to registeredSkeletons
skeleton := entry.skeleton
delete(cm.chansSkeletons, skeleton)
entry.skeleton = ""
cm.chans[cfname] = entry
cm.registeredChannels.Add(cfname) cm.registeredChannels.Add(cfname)
if skel, err := Skeleton(channel.Name()); err == nil { cm.registeredSkeletons.Add(skeleton)
cm.registeredSkeletons.Add(skel)
}
return nil return nil
} }
@ -252,8 +255,12 @@ func (cm *ChannelManager) SetUnregistered(channelName string, account string) (e
if entry != nil { if entry != nil {
entry.channel.SetUnregistered(account) entry.channel.SetUnregistered(account)
delete(cm.registeredChannels, cfname) delete(cm.registeredChannels, cfname)
// transfer the skeleton from registeredSkeletons to chansSkeletons
if skel, err := Skeleton(entry.channel.Name()); err == nil { if skel, err := Skeleton(entry.channel.Name()); err == nil {
delete(cm.registeredSkeletons, skel) delete(cm.registeredSkeletons, skel)
cm.chansSkeletons.Add(skel)
entry.skeleton = skel
cm.chans[cfname] = entry
} }
} }
return nil return nil
@ -261,7 +268,7 @@ func (cm *ChannelManager) SetUnregistered(channelName string, account string) (e
// Rename renames a channel (but does not notify the members) // Rename renames a channel (but does not notify the members)
func (cm *ChannelManager) Rename(name string, newName string) (err error) { func (cm *ChannelManager) Rename(name string, newName string) (err error) {
cfname, err := CasefoldChannel(name) oldCfname, err := CasefoldChannel(name)
if err != nil { if err != nil {
return errNoSuchChannel return errNoSuchChannel
} }
@ -289,41 +296,44 @@ func (cm *ChannelManager) Rename(name string, newName string) (err error) {
cm.Lock() cm.Lock()
defer cm.Unlock() defer cm.Unlock()
if newCfname == cfname { entry := cm.chans[oldCfname]
entry := cm.chans[cfname]
if entry == nil || !entry.channel.IsLoaded() {
return errNoSuchChannel
}
entry.channel.Rename(newName, cfname)
return nil
}
if cm.chans[newCfname] != nil || cm.registeredChannels.Has(newCfname) {
return errChannelNameInUse
}
if cm.chansSkeletons.Has(newSkeleton) || cm.registeredSkeletons.Has(newSkeleton) {
return errChannelNameInUse
}
entry := cm.chans[cfname]
if entry == nil || !entry.channel.IsLoaded() { if entry == nil || !entry.channel.IsLoaded() {
return errNoSuchChannel return errNoSuchChannel
} }
channel = entry.channel channel = entry.channel
info = channel.ExportRegistration(IncludeInitial) info = channel.ExportRegistration(IncludeInitial)
registered := info.Founder != "" registered := info.Founder != ""
delete(cm.chans, cfname)
oldSkeleton, err := Skeleton(info.Name)
if err != nil {
return errNoSuchChannel // ugh
}
if newCfname != oldCfname {
if cm.chans[newCfname] != nil || cm.registeredChannels.Has(newCfname) {
return errChannelNameInUse
}
}
if oldSkeleton != newSkeleton {
if cm.chansSkeletons.Has(newSkeleton) || cm.registeredSkeletons.Has(newSkeleton) {
return errConfusableIdentifier
}
}
delete(cm.chans, oldCfname)
if !registered {
entry.skeleton = newSkeleton
}
cm.chans[newCfname] = entry cm.chans[newCfname] = entry
if registered { if registered {
delete(cm.registeredChannels, cfname) delete(cm.registeredChannels, oldCfname)
if oldSkeleton, err := Skeleton(info.Name); err == nil {
delete(cm.registeredSkeletons, oldSkeleton)
}
cm.registeredChannels.Add(newCfname) cm.registeredChannels.Add(newCfname)
delete(cm.registeredSkeletons, oldSkeleton)
cm.registeredSkeletons.Add(newSkeleton) cm.registeredSkeletons.Add(newSkeleton)
} else { } else {
delete(cm.chansSkeletons, entry.skeleton) delete(cm.chansSkeletons, oldSkeleton)
cm.chansSkeletons.Add(newSkeleton) cm.chansSkeletons.Add(newSkeleton)
entry.skeleton = newSkeleton
cm.chans[cfname] = entry
} }
entry.channel.Rename(newName, newCfname) entry.channel.Rename(newName, newCfname)
return nil return nil

View File

@ -2643,7 +2643,7 @@ func renameHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Re
err := server.channels.Rename(oldName, newName) err := server.channels.Rename(oldName, newName)
if err == errInvalidChannelName { if err == errInvalidChannelName {
rb.Add(nil, server.name, ERR_NOSUCHCHANNEL, client.Nick(), utils.SafeErrorParam(newName), client.t(err.Error())) rb.Add(nil, server.name, ERR_NOSUCHCHANNEL, client.Nick(), utils.SafeErrorParam(newName), client.t(err.Error()))
} else if err == errChannelNameInUse { } else if err == errChannelNameInUse || err == errConfusableIdentifier {
rb.Add(nil, server.name, "FAIL", "RENAME", "CHANNEL_NAME_IN_USE", oldName, utils.SafeErrorParam(newName), client.t(err.Error())) rb.Add(nil, server.name, "FAIL", "RENAME", "CHANNEL_NAME_IN_USE", oldName, utils.SafeErrorParam(newName), client.t(err.Error()))
} else if err != nil { } else if err != nil {
rb.Add(nil, server.name, "FAIL", "RENAME", "CANNOT_RENAME", oldName, utils.SafeErrorParam(newName), client.t("Cannot rename channel")) rb.Add(nil, server.name, "FAIL", "RENAME", "CANNOT_RENAME", oldName, utils.SafeErrorParam(newName), client.t("Cannot rename channel"))