@@ -14,6 +14,7 @@ import (
14
14
"path/filepath"
15
15
"regexp"
16
16
"strings"
17
+ "sync"
17
18
"time"
18
19
"unicode"
19
20
@@ -417,19 +418,9 @@ func (u *User) DisplayName() string {
417
418
return u .Name
418
419
}
419
420
420
- var emailToReplacer = strings .NewReplacer (
421
- "\n " , "" ,
422
- "\r " , "" ,
423
- "<" , "" ,
424
- ">" , "" ,
425
- "," , "" ,
426
- ":" , "" ,
427
- ";" , "" ,
428
- )
429
-
430
421
// EmailTo returns a string suitable to be put into a e-mail `To:` header.
431
422
func (u * User ) EmailTo () string {
432
- sanitizedDisplayName := emailToReplacer .Replace (u .DisplayName ())
423
+ sanitizedDisplayName := globalVars (). emailToReplacer .Replace (u .DisplayName ())
433
424
434
425
// should be an edge case but nice to have
435
426
if sanitizedDisplayName == u .Email {
@@ -526,28 +517,52 @@ func GetUserSalt() (string, error) {
526
517
if err != nil {
527
518
return "" , err
528
519
}
529
- // Returns a 32 bytes long string.
520
+ // Returns a 32-byte long string.
530
521
return hex .EncodeToString (rBytes ), nil
531
522
}
532
523
533
- // Note: The set of characters here can safely expand without a breaking change,
534
- // but characters removed from this set can cause user account linking to break
535
- var (
536
- customCharsReplacement = strings .NewReplacer ("Æ" , "AE" )
537
- removeCharsRE = regexp .MustCompile ("['`´]" )
538
- transformDiacritics = transform .Chain (norm .NFD , runes .Remove (runes .In (unicode .Mn )), norm .NFC )
539
- replaceCharsHyphenRE = regexp .MustCompile (`[\s~+]` )
540
- )
524
+ type globalVarsStruct struct {
525
+ customCharsReplacement * strings.Replacer
526
+ removeCharsRE * regexp.Regexp
527
+ transformDiacritics transform.Transformer
528
+ replaceCharsHyphenRE * regexp.Regexp
529
+ emailToReplacer * strings.Replacer
530
+ emailRegexp * regexp.Regexp
531
+ }
532
+
533
+ var globalVars = sync .OnceValue (func () * globalVarsStruct {
534
+ return & globalVarsStruct {
535
+ // Note: The set of characters here can safely expand without a breaking change,
536
+ // but characters removed from this set can cause user account linking to break
537
+ customCharsReplacement : strings .NewReplacer ("Æ" , "AE" ),
538
+
539
+ removeCharsRE : regexp .MustCompile ("['`´]" ),
540
+ transformDiacritics : transform .Chain (norm .NFD , runes .Remove (runes .In (unicode .Mn )), norm .NFC ),
541
+ replaceCharsHyphenRE : regexp .MustCompile (`[\s~+]` ),
542
+
543
+ emailToReplacer : strings .NewReplacer (
544
+ "\n " , "" ,
545
+ "\r " , "" ,
546
+ "<" , "" ,
547
+ ">" , "" ,
548
+ "," , "" ,
549
+ ":" , "" ,
550
+ ";" , "" ,
551
+ ),
552
+ emailRegexp : regexp .MustCompile ("^[a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]*@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\ .[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$" ),
553
+ }
554
+ })
541
555
542
556
// NormalizeUserName only takes the name part if it is an email address, transforms it diacritics to ASCII characters.
543
557
// It returns a string with the single-quotes removed, and any other non-supported username characters are replaced with a `-` character
544
558
func NormalizeUserName (s string ) (string , error ) {
559
+ vars := globalVars ()
545
560
s , _ , _ = strings .Cut (s , "@" )
546
- strDiacriticsRemoved , n , err := transform .String (transformDiacritics , customCharsReplacement .Replace (s ))
561
+ strDiacriticsRemoved , n , err := transform .String (vars . transformDiacritics , vars . customCharsReplacement .Replace (s ))
547
562
if err != nil {
548
563
return "" , fmt .Errorf ("failed to normalize the string of provided username %q at position %d" , s , n )
549
564
}
550
- return replaceCharsHyphenRE .ReplaceAllLiteralString (removeCharsRE .ReplaceAllLiteralString (strDiacriticsRemoved , "" ), "-" ), nil
565
+ return vars . replaceCharsHyphenRE .ReplaceAllLiteralString (vars . removeCharsRE .ReplaceAllLiteralString (strDiacriticsRemoved , "" ), "-" ), nil
551
566
}
552
567
553
568
var (
0 commit comments