-
Notifications
You must be signed in to change notification settings - Fork 0
/
txtsanitize.go
65 lines (60 loc) · 1.81 KB
/
txtsanitize.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
package txtsanitize
import (
"bytes"
"strings"
)
// TXTSanitize - attempts to make sure that the return value is enclosed in
// double quotes, and any embedded double quotes are escaped properly with `\`.
// It honors pre-escaped sequences inside, in that it ignores all but those
// preceding an embedded double quote. The return value is idempotent, meaning
// you can feed the output back into TXTSanitize and you should get the same
// result as the initial call. This is important so that we don't re-escape
// things such as in the case when reading a TXT record from an API call and
// sending the payload back in a subsequent update call.
func TXTSanitize(in string) string {
quoted, contents := false, []byte(in)
if len(in) >= 2 {
quoted = contents[0] == '"' && contents[len(in)-1] == '"'
}
if quoted {
contents = contents[1 : len(in)-1]
}
escaped := 0
var bldr, out strings.Builder
for ind := 0; ind < len(contents); ind++ {
tInd := bytes.IndexByte(contents[ind:], '"')
if tInd == -1 {
bldr.Write(contents[ind:])
break
}
bldr.Write(contents[ind : ind+tInd])
ind += tInd
// look for \", but be aware of \\" is not escaped, but \\\" is
escCt := 0
for j := ind - 1; j >= 0 && contents[j] == '\\'; j-- {
escCt++
}
if escCt%2 == 0 {
// add escape
escaped++
bldr.WriteByte('\\')
}
bldr.WriteByte('"')
}
// This tries to catch the situation where we have something like:
// "foo" and other stuff "bar"
// and make sure we get:
// "\"foo\" and other stuff \"bar\""
// which is likely what we want, instead of:
// "foo\" and other stuff \"bar"
out.WriteByte('"')
if quoted && escaped > 0 && escaped%2 == 0 {
out.WriteString(`\"`)
out.WriteString(bldr.String())
out.WriteString(`\"`)
} else {
out.WriteString(bldr.String())
}
out.WriteByte('"')
return out.String()
}