mirror of
https://github.com/mjl-/mox.git
synced 2025-07-10 06:34:40 +03:00
imapserver: fix interpreting the first "*" in sequence/uid patterns, like "*:123" or plain "*"
in some cases, they were interpreted as meaning "the first sequence/uid", but it should always be "the last sequence/uid", just like patterns of the form "123:*". this wrong interpretation was used in the "fetch" command when combined with "changedsince", and in the search command for some parameters, and during expunge with an explicit uid range. the form "*" and "*:123" aren't very common.
This commit is contained in:
@ -38,29 +38,37 @@ func TestNumSetContains(t *testing.T) {
|
||||
|
||||
// 2:*
|
||||
ss2 := numSet{false, []numRange{{*num(2), star}}}
|
||||
check(!ss2.containsSeq(1, []store.UID{2}, nil))
|
||||
check(ss2.containsSeq(1, []store.UID{2}, nil))
|
||||
check(!ss2.containsSeq(2, []store.UID{2}, nil))
|
||||
check(ss2.containsSeq(2, []store.UID{4, 5}, nil))
|
||||
check(ss2.containsSeq(3, []store.UID{4, 5, 6}, nil))
|
||||
check(!ss2.containsSeq(4, []store.UID{4, 5, 6}, nil))
|
||||
|
||||
check(ss2.containsUID(2, []store.UID{2}, nil))
|
||||
check(!ss2.containsUID(1, []store.UID{1, 2, 3}, nil))
|
||||
check(ss2.containsUID(3, []store.UID{1, 2, 3}, nil))
|
||||
check(ss2.containsUID(2, []store.UID{2}, nil))
|
||||
check(!ss2.containsUID(2, []store.UID{4, 5}, nil))
|
||||
check(!ss2.containsUID(2, []store.UID{1}, nil))
|
||||
|
||||
check(ss2.containsUID(2, []store.UID{2, 6}, nil))
|
||||
check(ss2.containsUID(6, []store.UID{2, 6}, nil))
|
||||
|
||||
// *:2
|
||||
// *:2, same as 2:*
|
||||
ss3 := numSet{false, []numRange{{*star, num(2)}}}
|
||||
check(ss3.containsSeq(1, []store.UID{2}, nil))
|
||||
check(!ss3.containsSeq(2, []store.UID{2}, nil))
|
||||
check(ss3.containsSeq(2, []store.UID{4, 5}, nil))
|
||||
check(!ss3.containsSeq(3, []store.UID{1, 2, 3}, nil))
|
||||
check(ss3.containsSeq(3, []store.UID{4, 5, 6}, nil))
|
||||
check(!ss3.containsSeq(4, []store.UID{4, 5, 6}, nil))
|
||||
|
||||
check(ss3.containsUID(1, []store.UID{1}, nil))
|
||||
check(ss3.containsUID(2, []store.UID{1, 2, 3}, nil))
|
||||
check(!ss3.containsUID(1, []store.UID{2, 3}, nil))
|
||||
check(!ss3.containsUID(3, []store.UID{1, 2, 3}, nil))
|
||||
check(ss3.containsUID(2, []store.UID{2}, nil))
|
||||
check(!ss3.containsUID(1, []store.UID{1, 2, 3}, nil))
|
||||
check(ss3.containsUID(3, []store.UID{1, 2, 3}, nil))
|
||||
check(!ss3.containsUID(2, []store.UID{4, 5}, nil))
|
||||
check(!ss3.containsUID(2, []store.UID{1}, nil))
|
||||
|
||||
check(ss3.containsUID(2, []store.UID{2, 6}, nil))
|
||||
check(ss3.containsUID(6, []store.UID{2, 6}, nil))
|
||||
}
|
||||
|
||||
func TestNumSetInterpret(t *testing.T) {
|
||||
@ -82,10 +90,25 @@ func TestNumSetInterpret(t *testing.T) {
|
||||
checkEqual([]store.UID{1}, "1:*", "1")
|
||||
checkEqual([]store.UID{1, 3}, "1:*", "1:3")
|
||||
checkEqual([]store.UID{1, 3}, "4:*", "3")
|
||||
checkEqual([]store.UID{2, 3}, "*:4", "2:4")
|
||||
checkEqual([]store.UID{2, 3}, "*:1", "2")
|
||||
checkEqual([]store.UID{1, 3}, "*:4", "3")
|
||||
checkEqual([]store.UID{2, 3}, "*:4", "3")
|
||||
checkEqual([]store.UID{2, 3}, "*:1", "1:3")
|
||||
checkEqual([]store.UID{2, 3}, "1:*", "1:3")
|
||||
checkEqual([]store.UID{1, 2, 3}, "1,2,3", "1,2,3")
|
||||
checkEqual([]store.UID{}, "1,2,3", "1,2,3")
|
||||
checkEqual([]store.UID{}, "1:3", "1:3")
|
||||
checkEqual([]store.UID{}, "3:1", "1:3")
|
||||
checkEqual([]store.UID{}, "1,2,3", "")
|
||||
checkEqual([]store.UID{}, "1:3", "")
|
||||
checkEqual([]store.UID{}, "3:1", "")
|
||||
|
||||
iter := parseNumSet("1:3").interpretStar([]store.UID{}).newIter()
|
||||
if _, ok := iter.Next(); ok {
|
||||
t.Fatalf("expected immediate end for empty iter")
|
||||
}
|
||||
|
||||
iter = parseNumSet("3:1").interpretStar([]store.UID{1, 2}).newIter()
|
||||
v0, _ := iter.Next()
|
||||
v1, _ := iter.Next()
|
||||
_, ok := iter.Next()
|
||||
if v0 != 1 || v1 != 2 || ok {
|
||||
t.Fatalf("got %v %v %v, expected 1, 2, false", v0, v1, ok)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user