Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions internal/im/matrix_adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -832,7 +832,10 @@ const matrixLocalPartContChars = "abcdefghijklmnopqrstuvwxyz0123456789._=-+/"
// mentionsLocalPart reports whether text contains "@localpart" NOT followed
// by a legal localpart continuation character (RE2-safe boundary).
func mentionsLocalPart(lower, localPart string) bool {
needle := "@" + localPart
// #2749 case follow-up: the old (?i) regex was case-insensitive, and
// self-hosted homeservers may issue mixed-case localparts (@Bot:...).
// The body is already lowered by callers; lower the needle too.
needle := "@" + strings.ToLower(localPart)
for start := 0; ; {
i := strings.Index(lower[start:], needle)
if i < 0 {
Expand All @@ -851,7 +854,8 @@ func mentionsLocalPart(lower, localPart string) bool {
// prefixes of a longer handle (same boundary rule as mentionsLocalPart).
func stripLocalPartMention(text, localPart string) string {
lower := strings.ToLower(text)
needle := "@" + localPart
// #2749 case follow-up: lower the needle to match the (?i) behavior.
needle := "@" + strings.ToLower(localPart)
var b strings.Builder
for i := 0; i < len(text); {
if strings.HasPrefix(lower[i:], needle) {
Expand Down
19 changes: 19 additions & 0 deletions internal/im/zz_issue2749_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,22 @@ func TestIssue2749_WordEndingLocalpartUnchanged(t *testing.T) {
t.Errorf("prefix confusion regression")
}
}

func TestIssue2749_MixedCaseLocalpart(t *testing.T) {
// #2749 case follow-up: self-hosted homeservers may issue mixed-case
// localparts; the old (?i) regex matched them. Lower both sides.
a := &matrixAdapter{userID: "@Bot-:matrix.org"}
if !a.hasMention("@Bot- check the build", nil) {
t.Errorf("mixed-case non-word-ending mention must match")
}
if !a.hasMention("hey @BOT- run tests", nil) {
t.Errorf("uppercase body mention of mixed-case localpart must match")
}
b := &matrixAdapter{userID: "@Al:matrix.org"}
if !b.hasMention("@al do it", nil) {
t.Errorf("lowercase body mention of uppercase localpart must match")
}
if got := a.stripMention("@Bot- check the build"); got != "check the build" {
t.Errorf("stripMention mixed-case = %q, want %q", got, "check the build")
}
}
Loading