Skip to content

Commit 0248c86

Browse files
committed
fix #1733
1 parent cdf7638 commit 0248c86

File tree

3 files changed

+153
-3
lines changed

3 files changed

+153
-3
lines changed

coolq/cqcode/element.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ package cqcode
22

33
import (
44
"bytes"
5-
"strconv"
65
"strings"
76

87
"github.com/Mrs4s/MiraiGo/binary"
8+
"github.com/Mrs4s/go-cqhttp/global"
99
)
1010

1111
// Element single message
@@ -60,7 +60,7 @@ func (e *Element) MarshalJSON() ([]byte, error) {
6060
buf.WriteByte('"')
6161
buf.WriteString(data.K)
6262
buf.WriteString(`":`)
63-
buf.WriteString(strconv.Quote(data.V))
63+
buf.WriteString(global.Quote(data.V))
6464
}
6565
buf.WriteString(`}}`)
6666
}), nil

coolq/event.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,11 @@ func (ev *event) MarshalJSON() ([]byte, error) {
6161
fmt.Fprintf(buf, `,"sub_type":"%s"`, ev.SubType)
6262
}
6363
for k, v := range ev.Others {
64-
v, _ := json.Marshal(v)
64+
v, err := json.Marshal(v)
65+
if err != nil {
66+
log.Warnf("marshal message payload error: %v", err)
67+
return nil, err
68+
}
6569
fmt.Fprintf(buf, `,"%s":%s`, k, v)
6670
}
6771
buf.WriteByte('}')

global/quote.go

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
package global
2+
3+
import (
4+
"strconv"
5+
"unicode/utf8"
6+
)
7+
8+
const (
9+
lowerhex = "0123456789abcdef"
10+
upperhex = "0123456789ABCDEF"
11+
)
12+
13+
// Quote returns a double-quoted Go string literal representing s. The
14+
// returned string uses Go escape sequences (\t, \n, \xFF, \u0100) for
15+
// control characters and non-printable characters as defined by
16+
// IsPrint.
17+
func Quote(s string) string {
18+
return quoteWith(s, '"', false, false)
19+
}
20+
21+
func quoteWith(s string, quote byte, ASCIIonly, graphicOnly bool) string {
22+
return string(appendQuotedWith(make([]byte, 0, 3*len(s)/2), s, quote, ASCIIonly, graphicOnly))
23+
}
24+
25+
func appendQuotedWith(buf []byte, s string, quote byte, ASCIIonly, graphicOnly bool) []byte {
26+
// Often called with big strings, so preallocate. If there's quoting,
27+
// this is conservative but still helps a lot.
28+
if cap(buf)-len(buf) < len(s) {
29+
nBuf := make([]byte, len(buf), len(buf)+1+len(s)+1)
30+
copy(nBuf, buf)
31+
buf = nBuf
32+
}
33+
buf = append(buf, quote)
34+
for width := 0; len(s) > 0; s = s[width:] {
35+
r := rune(s[0])
36+
width = 1
37+
if r >= utf8.RuneSelf {
38+
r, width = utf8.DecodeRuneInString(s)
39+
}
40+
if width == 1 && r == utf8.RuneError {
41+
buf = append(buf, `\x`...)
42+
buf = append(buf, lowerhex[s[0]>>4])
43+
buf = append(buf, lowerhex[s[0]&0xF])
44+
continue
45+
}
46+
buf = appendEscapedRune(buf, r, quote, ASCIIonly, graphicOnly)
47+
}
48+
buf = append(buf, quote)
49+
return buf
50+
}
51+
func appendEscapedRune(buf []byte, r rune, quote byte, ASCIIonly, graphicOnly bool) []byte {
52+
var runeTmp [utf8.UTFMax]byte
53+
if r == rune(quote) || r == '\\' { // always backslashed
54+
buf = append(buf, '\\')
55+
buf = append(buf, byte(r))
56+
return buf
57+
}
58+
if ASCIIonly {
59+
if r < utf8.RuneSelf && strconv.IsPrint(r) {
60+
buf = append(buf, byte(r))
61+
return buf
62+
}
63+
} else if strconv.IsPrint(r) || graphicOnly && isInGraphicList(r) {
64+
n := utf8.EncodeRune(runeTmp[:], r)
65+
buf = append(buf, runeTmp[:n]...)
66+
return buf
67+
}
68+
switch r {
69+
case '\a':
70+
buf = append(buf, `\a`...)
71+
case '\b':
72+
buf = append(buf, `\b`...)
73+
case '\f':
74+
buf = append(buf, `\f`...)
75+
case '\n':
76+
buf = append(buf, `\n`...)
77+
case '\r':
78+
buf = append(buf, `\r`...)
79+
case '\t':
80+
buf = append(buf, `\t`...)
81+
case '\v':
82+
buf = append(buf, `\v`...)
83+
default:
84+
switch {
85+
case !utf8.ValidRune(r):
86+
r = 0xFFFD
87+
fallthrough
88+
case r < 0x10000:
89+
buf = append(buf, `\u`...)
90+
for s := 12; s >= 0; s -= 4 {
91+
buf = append(buf, lowerhex[r>>uint(s)&0xF])
92+
}
93+
default:
94+
buf = append(buf, `\U`...)
95+
for s := 28; s >= 0; s -= 4 {
96+
buf = append(buf, lowerhex[r>>uint(s)&0xF])
97+
}
98+
}
99+
}
100+
return buf
101+
}
102+
103+
func isInGraphicList(r rune) bool {
104+
// We know r must fit in 16 bits - see makeisprint.go.
105+
if r > 0xFFFF {
106+
return false
107+
}
108+
rr := uint16(r)
109+
i := bsearch16(isGraphic, rr)
110+
return i < len(isGraphic) && rr == isGraphic[i]
111+
}
112+
113+
// bsearch16 returns the smallest i such that a[i] >= x.
114+
// If there is no such i, bsearch16 returns len(a).
115+
func bsearch16(a []uint16, x uint16) int {
116+
i, j := 0, len(a)
117+
for i < j {
118+
h := i + (j-i)>>1
119+
if a[h] < x {
120+
i = h + 1
121+
} else {
122+
j = h
123+
}
124+
}
125+
return i
126+
}
127+
128+
// isGraphic lists the graphic runes not matched by IsPrint.
129+
var isGraphic = []uint16{
130+
0x00a0,
131+
0x1680,
132+
0x2000,
133+
0x2001,
134+
0x2002,
135+
0x2003,
136+
0x2004,
137+
0x2005,
138+
0x2006,
139+
0x2007,
140+
0x2008,
141+
0x2009,
142+
0x200a,
143+
0x202f,
144+
0x205f,
145+
0x3000,
146+
}

0 commit comments

Comments
 (0)