hosts.go RawHistoryFolder
1// SPDX-License-Identifier: AGPL-3.0-or-later
2
3// Package mediapolicy shares the external video host policy between HTTP and Markdown.
4package mediapolicy
5
6import (
7 "fmt"
8 "net/url"
9 "strings"
10)
11
12// Defaults includes GitHub's user-attachment redirect destination.
13const Defaults = "github.com,user-images.githubusercontent.com,private-user-images.githubusercontent.com,github-production-user-asset-6210df.s3.amazonaws.com"
14
15// Parse accepts comma-separated exact DNS hostnames, never CSP expressions or URLs.
16func Parse(value string) ([]string, error) {
17 if value == "" {
18 value = Defaults
19 }
20 var hosts []string
21 for _, raw := range strings.Split(value, ",") {
22 host := strings.ToLower(strings.TrimSpace(raw))
23 if len(host) == 0 || len(host) > 253 {
24 return nil, fmt.Errorf("must contain exact DNS hostnames")
25 }
26 for _, label := range strings.Split(host, ".") {
27 if len(label) == 0 || len(label) > 63 || label[0] == '-' || label[len(label)-1] == '-' {
28 return nil, fmt.Errorf("must contain exact DNS hostnames")
29 }
30 for _, c := range label {
31 if (c < 'a' || c > 'z') && (c < '0' || c > '9') && c != '-' {
32 return nil, fmt.Errorf("must contain exact DNS hostnames")
33 }
34 }
35 }
36 hosts = append(hosts, host)
37 }
38 return hosts, nil
39}
40
41// Hosts supplies defaults for adapters constructed without explicit configuration.
42func Hosts(hosts []string) []string {
43 if hosts != nil {
44 return hosts
45 }
46 defaults, _ := Parse("")
47 return defaults
48}
49
50// Allows accepts only HTTP(S), without credentials or nonstandard ports.
51func Allows(u *url.URL, hosts []string) bool {
52 if u == nil || u.User != nil || (u.Scheme != "https" && u.Scheme != "http") {
53 return false
54 }
55 if port := u.Port(); port != "" && (u.Scheme != "https" || port != "443") && (u.Scheme != "http" || port != "80") {
56 return false
57 }
58 for _, host := range Hosts(hosts) {
59 if strings.EqualFold(u.Hostname(), host) {
60 return true
61 }
62 }
63 return false
64}
65
66// Sources returns explicit scheme sources, matching Allows and forbidding wildcards.
67func Sources(hosts []string) string {
68 var sources []string
69 for _, host := range Hosts(hosts) {
70 sources = append(sources, "https://"+host, "http://"+host)
71 }
72 return strings.Join(sources, " ")
73}