fix(terminal): prevent UTF-8 chunk truncation falling back to GBK
This fixes an issue where outputting large amounts of Chinese text caused the 4096-byte chunk to split a multi-byte UTF-8 character, falsely triggering the GBK fallback logic and resulting in garbled text.
This commit is contained in:
@@ -138,14 +138,40 @@ func (tc *TerminalController) handlePtyMode(conn *websocket.Conn, userID string)
|
|||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
buf := make([]byte, 4096)
|
buf := make([]byte, 4096)
|
||||||
|
var remainder []byte
|
||||||
for {
|
for {
|
||||||
n, err := ptmx.Read(buf)
|
n, err := ptmx.Read(buf)
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
text := toUTF8(buf[:n])
|
chunk := append(remainder, buf[:n]...)
|
||||||
writeMessage([]byte(text))
|
lastSafe := len(chunk)
|
||||||
|
for i := len(chunk); i > 0 && i > len(chunk)-4; i-- {
|
||||||
|
if utf8.RuneStart(chunk[i-1]) {
|
||||||
|
if !utf8.FullRune(chunk[i-1 : len(chunk)]) {
|
||||||
|
lastSafe = i - 1
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
safe := chunk[:lastSafe]
|
||||||
|
|
||||||
|
if len(safe) == 0 && len(chunk) >= 4 {
|
||||||
|
safe = chunk
|
||||||
|
remainder = nil
|
||||||
|
} else {
|
||||||
|
remainder = make([]byte, len(chunk[lastSafe:]))
|
||||||
|
copy(remainder, chunk[lastSafe:])
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(safe) > 0 {
|
||||||
|
text := toUTF8(safe)
|
||||||
|
writeMessage([]byte(text))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
if len(remainder) > 0 {
|
||||||
|
writeMessage([]byte(toUTF8(remainder)))
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@@ -259,14 +285,40 @@ func (tc *TerminalController) handlePipeMode(conn *websocket.Conn, userID string
|
|||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
defer func() { recover() }()
|
defer func() { recover() }()
|
||||||
buf := make([]byte, 4096)
|
buf := make([]byte, 4096)
|
||||||
|
var remainder []byte
|
||||||
for {
|
for {
|
||||||
n, err := reader.Read(buf)
|
n, err := reader.Read(buf)
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
text := toUTF8(buf[:n])
|
chunk := append(remainder, buf[:n]...)
|
||||||
writeMessage([]byte(text))
|
lastSafe := len(chunk)
|
||||||
|
for i := len(chunk); i > 0 && i > len(chunk)-4; i-- {
|
||||||
|
if utf8.RuneStart(chunk[i-1]) {
|
||||||
|
if !utf8.FullRune(chunk[i-1 : len(chunk)]) {
|
||||||
|
lastSafe = i - 1
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
safe := chunk[:lastSafe]
|
||||||
|
|
||||||
|
if len(safe) == 0 && len(chunk) >= 4 {
|
||||||
|
safe = chunk
|
||||||
|
remainder = nil
|
||||||
|
} else {
|
||||||
|
remainder = make([]byte, len(chunk[lastSafe:]))
|
||||||
|
copy(remainder, chunk[lastSafe:])
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(safe) > 0 {
|
||||||
|
text := toUTF8(safe)
|
||||||
|
writeMessage([]byte(text))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
if len(remainder) > 0 {
|
||||||
|
writeMessage([]byte(toUTF8(remainder)))
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user