mirror of
https://github.com/amir20/dozzle.git
synced 2026-06-23 04:10:12 +00:00
fix: strip control bytes when copying logs to clipboard (#4762)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
package container
|
||||
|
||||
import "strings"
|
||||
|
||||
// stripControlBytes removes C0 control characters except tab (\x09), newline
|
||||
// (\x0a) and carriage return (\x0d). A NUL byte terminates the clipboard string
|
||||
// on Windows, dropping everything after it.
|
||||
func stripControlBytes(r rune) rune {
|
||||
if (r >= 0x00 && r <= 0x08) || r == 0x0b || r == 0x0c || (r >= 0x0e && r <= 0x1f) {
|
||||
return -1
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// SanitizeForPlainText strips ANSI escape sequences and control bytes so log
|
||||
// text is safe to copy to the clipboard or open in a text editor.
|
||||
func SanitizeForPlainText(str string) string {
|
||||
return strings.Map(stripControlBytes, StripANSI(str))
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package container
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestSanitizeForPlainText(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
expected string
|
||||
}{
|
||||
{"strips NUL bytes that truncate clipboard text on Windows", "before\x00after", "beforeafter"},
|
||||
{"strips other C0 control bytes", "a\x01b\x07c\x1fd", "abcd"},
|
||||
{"preserves tab, newline and carriage return", "a\tb\nc\r\nd", "a\tb\nc\r\nd"},
|
||||
{"removes ANSI escape sequences", "\x1b[31mred\x1b[0m text", "red text"},
|
||||
{"leaves plain text untouched", "plain log line", "plain log line"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := SanitizeForPlainText(tt.input); got != tt.expected {
|
||||
t.Errorf("SanitizeForPlainText(%q) = %q, want %q", tt.input, got, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -197,7 +197,8 @@ func (h *handler) fetchLogsBetweenDates(w http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
}
|
||||
if plainText {
|
||||
fmt.Fprintf(writer, "%s\n", event.RawMessage)
|
||||
// Strip ANSI and control bytes; a NUL byte truncates clipboard text on Windows
|
||||
fmt.Fprintf(writer, "%s\n", container.SanitizeForPlainText(event.RawMessage))
|
||||
} else if err := encoder.Encode(event); err != nil {
|
||||
log.Error().Err(err).Msg("error encoding log event")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user