Files
go-imap/backend/backendutil/flags.go
T
Robert G. JakaboskyandSimon Ser e7ff51b5d0 Fix issue with backendutils.UpdateFlags().
Now only the 'current' parameter is modified.  The same update operation
can be applied to multipe flag lists (i.e. multiple messages).

Applying the same UpdateFlags operation on multiple messages wasn't safe,
since the 'flags' (last parameter) was modified.

The 'SetFlags' operation wass returning 'flags' parameter.  Multiple messages
would have been sharing the same slice's backing store.  Future changes to one
message's flags wouldd corrupt the other messages flags.

The 'RemoveFlags' operation was modifying the 'flags' parameter contents
(but not length).  So it wasn't safe to apply to multiple messages.
2019-12-06 11:32:32 +01:00

74 lines
1.6 KiB
Go

package backendutil
import (
"github.com/emersion/go-imap"
)
// UpdateFlags executes a flag operation on the flag set current.
func UpdateFlags(current []string, op imap.FlagsOp, flags []string) []string {
// Don't modify contents of 'flags' slice. Only modify 'current'.
// See https://github.com/golang/go/wiki/SliceTricks
// Re-use current's backing store
newFlags := current[:0]
switch op {
case imap.SetFlags:
hasRecent := false
// keep recent flag
for _, flag := range current {
if flag == imap.RecentFlag {
newFlags = append(newFlags, imap.RecentFlag)
hasRecent = true
break
}
}
// append new flags
for _, flag := range flags {
if flag == imap.RecentFlag {
// Make sure we don't add the recent flag multiple times.
if hasRecent {
// Already have the recent flag, skip.
continue
}
hasRecent = true
}
// append new flag
newFlags = append(newFlags, flag)
}
case imap.AddFlags:
// keep current flags
newFlags = current
// Only add new flag if it isn't already in current list.
for _, addFlag := range flags {
found := false
for _, flag := range current {
if addFlag == flag {
found = true
break
}
}
// new flag not found, add it.
if !found {
newFlags = append(newFlags, addFlag)
}
}
case imap.RemoveFlags:
// Filter current flags
for _, flag := range current {
remove := false
for _, removeFlag := range flags {
if removeFlag == flag {
remove = true
}
}
if !remove {
newFlags = append(newFlags, flag)
}
}
default:
// Unknown operation, return current flags unchanged
newFlags = current
}
return newFlags
}