- the HTML policy keeps rel on a when it holds only nofollow, sponsored and ugc tokens (D-83); any other rel value is removed - classes.MediaFileName slugs uploaded image names (lowercase, Polish letters transliterated, hyphens, at most 80 characters, image when empty) for the editor upload and POST /media/upload (D-85) - the editor corpus gains an external link with rel and a decorative image, pinned by TestEditorOutputPassesPolicy
62 lines
1.8 KiB
Go
62 lines
1.8 KiB
Go
package classes
|
||
|
||
import (
|
||
"path"
|
||
"regexp"
|
||
"strings"
|
||
)
|
||
|
||
// MaxMediaStem is the longest file name stem MediaFileName keeps (D-85).
|
||
const MaxMediaStem = 80
|
||
|
||
// mediaExtPattern is an extension MediaFileName keeps.
|
||
var mediaExtPattern = regexp.MustCompile(`^\.[a-z0-9]+$`)
|
||
|
||
// polishLetters transliterates the Polish diacritics (lower case).
|
||
var polishLetters = map[rune]rune{'ą': 'a', 'ć': 'c', 'ę': 'e', 'ł': 'l', 'ń': 'n', 'ó': 'o', 'ś': 's', 'ź': 'z', 'ż': 'z'}
|
||
|
||
// MediaFileName is the stored name of an uploaded image (D-85, the Blog
|
||
// Editor's J4 rule, applied on the server whatever the client sends): the
|
||
// base name's stem lowercased, Polish diacritics transliterated, every other
|
||
// run of characters outside a-z and 0-9 turned into one hyphen, trimmed and
|
||
// cut to MaxMediaStem characters, "image" when nothing is left; and its
|
||
// extension lowercased when it is a dot and letters or digits (dropped
|
||
// otherwise). "Lwia Grzywa – w lesie!.JPG" is "lwia-grzywa-w-lesie.jpg".
|
||
// The result needs no escaping in a URL or an src attribute.
|
||
func MediaFileName(name string) string {
|
||
base := path.Base(strings.ReplaceAll(name, `\`, "/"))
|
||
if base == "." || base == "/" {
|
||
base = ""
|
||
}
|
||
stem, ext := base, ""
|
||
if dot := strings.LastIndexByte(base, '.'); dot >= 0 {
|
||
if e := strings.ToLower(base[dot:]); mediaExtPattern.MatchString(e) {
|
||
stem, ext = base[:dot], e
|
||
}
|
||
}
|
||
var b strings.Builder
|
||
dash := false
|
||
for _, r := range strings.ToLower(stem) {
|
||
if t, ok := polishLetters[r]; ok {
|
||
r = t
|
||
}
|
||
if (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') {
|
||
b.WriteRune(r)
|
||
dash = false
|
||
continue
|
||
}
|
||
if !dash {
|
||
b.WriteByte('-')
|
||
dash = true
|
||
}
|
||
}
|
||
out := strings.Trim(b.String(), "-")
|
||
if len(out) > MaxMediaStem {
|
||
out = strings.TrimRight(out[:MaxMediaStem], "-")
|
||
}
|
||
if out == "" {
|
||
out = "image"
|
||
}
|
||
return out + ext
|
||
}
|