diff --git a/internal/regexes/regexes.go b/internal/regexes/regexes.go index 25fcfc03a..aca502345 100644 --- a/internal/regexes/regexes.go +++ b/internal/regexes/regexes.go @@ -47,6 +47,7 @@ const ( mentionFinder = `(?:^|\s)(@` + usernameGrp + `+(?:@` + domainGrp + `+)?)` // Extract all mentions from a text, each mention may include domain. emojiShortcode = `\w{2,30}` // Pattern for emoji shortcodes. maximumEmojiShortcodeLength = 30 emojiFinder = `(?:\b)?:(` + emojiShortcode + `):(?:\b)?` // Extract all emoji shortcodes from a text. + emojiValidator = `^` + emojiShortcode + `$` // Validate a single emoji shortcode. usernameStrict = `^[a-z0-9_]{1,64}$` // Pattern for usernames on THIS instance. maximumUsernameLength = 64 usernameRelaxed = `[a-z0-9_\.]{1,}` // Relaxed version of username that can match instance accounts too. misskeyReportNotesFinder = `(?m)(?:^Note: ((?:http|https):\/\/.*)$)` // Extract reported Note URIs from the text of a Misskey report/flag. @@ -95,8 +96,8 @@ var ( // MentionFinder extracts whole mentions from a piece of text. MentionFinder = regexp.MustCompile(mentionFinder) - // EmojiShortcode validates an emoji name. - EmojiShortcode = regexp.MustCompile(emojiShortcode) + // EmojiValidator validates an emoji shortcode. + EmojiValidator = regexp.MustCompile(emojiValidator) // EmojiFinder extracts emoji strings from a piece of text. // See: https://regex101.com/r/478XGM/1 diff --git a/internal/validate/formvalidation.go b/internal/validate/formvalidation.go index 1b5996b4b..3d1d05072 100644 --- a/internal/validate/formvalidation.go +++ b/internal/validate/formvalidation.go @@ -191,7 +191,7 @@ func CustomCSS(customCSS string) error { // for emoji shortcodes, to figure out whether it's a valid shortcode, ie., 2-30 characters, // a-zA-Z, numbers, and underscores. func EmojiShortcode(shortcode string) error { - if !regexes.EmojiShortcode.MatchString(shortcode) { + if !regexes.EmojiValidator.MatchString(shortcode) { return fmt.Errorf("shortcode %s did not pass validation, must be between 2 and 30 characters, letters, numbers, and underscores only", shortcode) } return nil diff --git a/internal/validate/formvalidation_test.go b/internal/validate/formvalidation_test.go index 40830407c..578b300ea 100644 --- a/internal/validate/formvalidation_test.go +++ b/internal/validate/formvalidation_test.go @@ -321,6 +321,63 @@ func (suite *ValidationTestSuite) TestValidateCustomCSSTooLongUnicode() { suite.EqualError(err, "custom_css must be less than 5 characters, but submitted custom_css was 10 characters") } +func (suite *ValidationTestSuite) TestValidateEmojiShortcode() { + type testStruct struct { + shortcode string + ok bool + } + + for _, test := range []testStruct{ + { + shortcode: "peepee", + ok: true, + }, + { + shortcode: "poo-poo", + ok: false, + }, + { + shortcode: "-peepee", + ok: false, + }, + { + shortcode: "p", + ok: false, + }, + { + shortcode: "pp", + ok: true, + }, + { + shortcode: "6969", + ok: true, + }, + { + shortcode: "__peepee", + ok: true, + }, + { + shortcode: "_", + ok: false, + }, + { + // Too long. + shortcode: "_XxX_Ultimate_Gamer_dude_6969_420_", + ok: false, + }, + { + shortcode: "_XxX_Ultimate_Gamer_dude_6969_", + ok: true, + }, + } { + err := validate.EmojiShortcode(test.shortcode) + ok := err == nil + if !suite.Equal(test.ok, ok) { + suite.T().Logf("fail on %s", test.shortcode) + } + } +} + func TestValidationTestSuite(t *testing.T) { suite.Run(t, new(ValidationTestSuite)) }