whitelist.go (2274B)
1 // Copyright 2021 The Hugo Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13
14 package security
15
16 import (
17 "encoding/json"
18 "fmt"
19 "regexp"
20 "strings"
21 )
22
23 const (
24 acceptNoneKeyword = "none"
25 )
26
27 // Whitelist holds a whitelist.
28 type Whitelist struct {
29 acceptNone bool
30 patterns []*regexp.Regexp
31
32 // Store this for debugging/error reporting
33 patternsStrings []string
34 }
35
36 func (w Whitelist) MarshalJSON() ([]byte, error) {
37 if w.acceptNone {
38 return json.Marshal(acceptNoneKeyword)
39 }
40
41 return json.Marshal(w.patternsStrings)
42 }
43
44 // NewWhitelist creates a new Whitelist from zero or more patterns.
45 // An empty patterns list or a pattern with the value 'none' will create
46 // a whitelist that will Accept noone.
47 func NewWhitelist(patterns ...string) Whitelist {
48 if len(patterns) == 0 {
49 return Whitelist{acceptNone: true}
50 }
51
52 var acceptSome bool
53 var patternsStrings []string
54
55 for _, p := range patterns {
56 if p == acceptNoneKeyword {
57 acceptSome = false
58 break
59 }
60
61 if ps := strings.TrimSpace(p); ps != "" {
62 acceptSome = true
63 patternsStrings = append(patternsStrings, ps)
64 }
65 }
66
67 if !acceptSome {
68 return Whitelist{
69 acceptNone: true,
70 }
71 }
72
73 var patternsr []*regexp.Regexp
74
75 for i := 0; i < len(patterns); i++ {
76 p := strings.TrimSpace(patterns[i])
77 if p == "" {
78 continue
79 }
80 patternsr = append(patternsr, regexp.MustCompile(p))
81 }
82
83 return Whitelist{patterns: patternsr, patternsStrings: patternsStrings}
84 }
85
86 // Accepted reports whether name is whitelisted.
87 func (w Whitelist) Accept(name string) bool {
88 if w.acceptNone {
89 return false
90 }
91
92 for _, p := range w.patterns {
93 if p.MatchString(name) {
94 return true
95 }
96 }
97 return false
98 }
99
100 func (w Whitelist) String() string {
101 return fmt.Sprint(w.patternsStrings)
102 }