feat(17-04): menu plugin admin with registry types, URL checks and tree reorder
- golem15.menu plugin, tables golem15_menu_menus and golem15_menu_menu_entries with the PHP columns plus a nullable url_pattern (D-02) - MenuEntry BeforeSave ports PHP beforeSave: nest columns 0, menu from the parent, sort_order after the menu's last - entry type dropdown: url, divider and the signpost registry types; reference depends on type through signpost.ReferenceOptions - URL scheme allowlist (errors.url_scheme), target _self or _blank, menu and parent cycle checks - menu filter, toolbar reorder/create/delete and config_reorder.yaml partitioned by menu - navigation Menus with Menus and Menu entries, permission golem15.menu.manage_menu, en and pl phrasebooks - TestMenuAdminSmoke
This commit is contained in:
46
classes/links.go
Normal file
46
classes/links.go
Normal file
@@ -0,0 +1,46 @@
|
||||
// Package classes holds the menu plugin's link rules and the tree the public
|
||||
// API serves.
|
||||
package classes
|
||||
|
||||
import "strings"
|
||||
|
||||
// AllowedURL reports whether an entry URL may be stored and served: empty, a
|
||||
// path starting with "/", a fragment starting with "#", or an absolute
|
||||
// http, https, mailto or tel URL (case-insensitive). Anything else, such as
|
||||
// javascript: or data:, is refused, and so is a URL with surrounding
|
||||
// whitespace or control characters, which browsers strip before reading the
|
||||
// scheme (RESEARCH Pitfall 15).
|
||||
func AllowedURL(url string) bool {
|
||||
if url == "" {
|
||||
return true
|
||||
}
|
||||
for _, r := range url {
|
||||
if r < 0x20 || r == 0x7f {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if strings.TrimSpace(url) != url {
|
||||
return false
|
||||
}
|
||||
if url[0] == '/' || url[0] == '#' {
|
||||
return true
|
||||
}
|
||||
lower := strings.ToLower(url)
|
||||
for _, prefix := range []string{"http://", "https://", "mailto:", "tel:"} {
|
||||
if strings.HasPrefix(lower, prefix) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// The link targets an entry may open in.
|
||||
const (
|
||||
TargetSelf = "_self"
|
||||
TargetBlank = "_blank"
|
||||
)
|
||||
|
||||
// AllowedTarget reports whether target is _self, _blank or empty.
|
||||
func AllowedTarget(target string) bool {
|
||||
return target == "" || target == TargetSelf || target == TargetBlank
|
||||
}
|
||||
Reference in New Issue
Block a user