/
encode_strings.go
109 lines (94 loc) · 2.92 KB
/
encode_strings.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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package goutil
import (
"bytes"
"encoding/json"
"io"
"strings"
"github.com/AspieSoft/go-regex-re2/v2"
)
type encodeHtml struct {}
var HTML *encodeHtml = &encodeHtml{}
type encodeJson struct {}
var JSON *encodeJson = &encodeJson{}
var regEscHTML *regex.Regexp = regex.Comp(`[<>&]`)
var regEscFixAmp *regex.Regexp = regex.Comp(`&(amp;)*`)
// EscapeHTML replaces HTML characters with html entities
//
// Also prevents and removes &amp; from results
func (encHtml *encodeHtml) Escape(html []byte) []byte {
html = regEscHTML.RepFunc(html, func(data func(int) []byte) []byte {
if bytes.Equal(data(0), []byte("<")) {
return []byte("<")
} else if bytes.Equal(data(0), []byte(">")) {
return []byte(">")
}
return []byte("&")
})
return regEscFixAmp.RepStrLit(html, []byte("&"))
}
var regEscHTMLArgs *regex.Regexp = regex.Comp(`([\\]*)([\\"'\'])`)
// EscapeHTMLArgs escapes quotes and backslashes for use within HTML quotes
// @quote can be used to only escape specific quotes or chars
func (encHtml *encodeHtml) EscapeArgs(html []byte, quote ...byte) []byte {
if len(quote) == 0 {
quote = []byte("\"'`")
}
return regEscHTMLArgs.RepFunc(html, func(data func(int) []byte) []byte {
if len(data(1)) % 2 == 0 && bytes.ContainsRune(quote, rune(data(2)[0])) {
// return append([]byte("\\"), data(2)...)
return regex.JoinBytes(data(1), '\\', data(2))
}
if bytes.ContainsRune(quote, rune(data(2)[0])) {
return append(data(1), data(2)...)
}
return data(0)
})
}
// StringifyJSON converts a map or array to a JSON string
func (encJson *encodeJson) Stringify(data interface{}, ind ...int) ([]byte, error) {
var res []byte
var err error
if len(ind) != 0 {
sp := " "
if len(ind) > 2 {
sp = strings.Repeat(" ", ind[1])
}
res, err = json.MarshalIndent(data, strings.Repeat(" ", ind[0]), sp)
}else{
res, err = json.Marshal(data)
}
if err != nil {
return []byte{}, err
}
res = bytes.ReplaceAll(res, []byte("\\u003c"), []byte("<"))
res = bytes.ReplaceAll(res, []byte("\\u003e"), []byte(">"))
return res, nil
}
// ParseJson converts a json string into a map of strings
func (encJson *encodeJson) Parse(b []byte) (map[string]interface{}, error) {
res := map[string]interface{}{}
err := json.Unmarshal(b, &res)
if err != nil {
return map[string]interface{}{}, err
}
return res, nil
}
// DecodeJSON is useful for decoding a JSON output from the body of an http request
//
// example: goutil.DecodeJSON(r.Body)
func (encJson *encodeJson) Decode(data io.Reader) (map[string]interface{}, error) {
var res map[string]interface{}
err := json.NewDecoder(data).Decode(&res)
if err != nil {
return nil, err
}
return res, nil
}
// DeepCopyJson will stringify and parse json to create a deep copy and escape pointers
func (encJson *encodeJson) DeepCopy(data map[string]interface{}) (map[string]interface{}, error) {
b, err := encJson.Stringify(data)
if err != nil {
return nil, err
}
return encJson.Parse(b)
}