-
Notifications
You must be signed in to change notification settings - Fork 0
/
sanitize.go
77 lines (61 loc) · 1.74 KB
/
sanitize.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package common
import (
"fmt"
"reflect"
"sync"
"github.com/microcosm-cc/bluemonday"
)
const (
maxPermissibleInputStringLength = 10000
maxPermissibleInputNumber = 5000000
)
var initializeHTMLSanitizer sync.Once
var htmlSanitizer *bluemonday.Policy
func getHTMLSanitizer() *bluemonday.Policy {
initializeHTMLSanitizer.Do(func() {
if htmlSanitizer == nil {
htmlSanitizer = bluemonday.UGCPolicy()
}
})
return htmlSanitizer
}
func Sanitize(rawInput interface{}) (interface{}, error) {
input := reflect.ValueOf(rawInput)
switch input.Kind() {
// Recursively sanitize all values of the map
case reflect.Map:
for _, key := range input.MapKeys() {
newValue, err := Sanitize(input.MapIndex(key).Interface())
if err != nil {
return rawInput, err
}
input.SetMapIndex(key, reflect.ValueOf(newValue))
}
// Recursively sanitize all values of the slice
case reflect.Slice:
for i := 0; i < input.Len(); i++ {
newValue, err := Sanitize(input.Index(i).Interface())
if err != nil {
return rawInput, err
}
input.Index(i).Set(reflect.ValueOf(newValue))
}
//Check for string length and sanitize the string using Bluemonday
case reflect.String:
rawInputString := rawInput.(string)
if len(rawInputString) > maxPermissibleInputStringLength {
return rawInput, fmt.Errorf("string length exceeded")
}
rawInput = getHTMLSanitizer().Sanitize(rawInputString)
// For int and float, if number exceeds 5 million, return error
case reflect.Int:
if rawInput.(int) > maxPermissibleInputNumber {
return rawInput, fmt.Errorf("number exceeded")
}
case reflect.Float64:
if rawInput.(float64) > maxPermissibleInputNumber {
return rawInput, fmt.Errorf("floating point number exceeded")
}
}
return rawInput, nil
}