82 lines
2.4 KiB
Go
82 lines
2.4 KiB
Go
package logging
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"fmt"
|
|
"mime"
|
|
"net/url"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// Inline attachments remain opaque in every log format, regardless of the
|
|
// carrier field or element. Only standard-decoded media type and byte count
|
|
// are projected; malformed declarations never restore their payload.
|
|
var inlineDataURI = regexp.MustCompile(`(?i)\bdata:[^,\s<>"']*,[^\s<>"']*`)
|
|
|
|
func redactInlineBinary(s string) string {
|
|
if strings.HasPrefix(strings.ToLower(strings.TrimSpace(s)), "data:") {
|
|
return inlineBinarySummary(strings.TrimSpace(s))
|
|
}
|
|
return inlineDataURI.ReplaceAllStringFunc(s, inlineBinarySummary)
|
|
}
|
|
|
|
// Repeated formatting must retain only our typed attachment projection.
|
|
func isInlineBinarySummary(s string) bool {
|
|
if !strings.HasPrefix(s, "[BINARY ") || !strings.HasSuffix(s, "]") {
|
|
return false
|
|
}
|
|
fields := strings.Fields(s[len("[BINARY ") : len(s)-1])
|
|
if len(fields) != 2 && len(fields) != 3 {
|
|
return false
|
|
}
|
|
if !strings.HasPrefix(fields[0], "type=") || !strings.HasPrefix(fields[1], "bytes=") {
|
|
return false
|
|
}
|
|
kind := strings.TrimPrefix(fields[0], "type=")
|
|
if kind != "unknown" {
|
|
media, params, err := mime.ParseMediaType(kind)
|
|
if err != nil || media != kind || !strings.Contains(media, "/") || len(params) != 0 {
|
|
return false
|
|
}
|
|
}
|
|
count := strings.TrimPrefix(fields[1], "bytes=")
|
|
if count != "unknown" {
|
|
if _, err := strconv.ParseUint(count, 10, 64); err != nil {
|
|
return false
|
|
}
|
|
}
|
|
return len(fields) == 2 || fields[2] == "error=invalid_data_uri"
|
|
}
|
|
|
|
func inlineBinarySummary(uri string) string {
|
|
header, payload, ok := strings.Cut(uri[5:], ",")
|
|
if !ok {
|
|
return "[BINARY type=unknown bytes=unknown error=invalid_data_uri]"
|
|
}
|
|
encoded := strings.HasSuffix(strings.ToLower(header), ";base64")
|
|
if encoded {
|
|
header = header[:len(header)-7]
|
|
}
|
|
if header == "" {
|
|
header = "text/plain;charset=US-ASCII"
|
|
}
|
|
media, _, err := mime.ParseMediaType(header)
|
|
if err != nil || !strings.Contains(media, "/") {
|
|
return "[BINARY type=unknown bytes=unknown error=invalid_data_uri]"
|
|
}
|
|
raw, err := url.PathUnescape(payload)
|
|
if err != nil {
|
|
return fmt.Sprintf("[BINARY type=%s bytes=unknown error=invalid_data_uri]", media)
|
|
}
|
|
data := []byte(raw)
|
|
if encoded {
|
|
data, err = base64.StdEncoding.DecodeString(raw)
|
|
if err != nil {
|
|
return fmt.Sprintf("[BINARY type=%s bytes=unknown error=invalid_data_uri]", media)
|
|
}
|
|
}
|
|
return fmt.Sprintf("[BINARY type=%s bytes=%d]", media, len(data))
|
|
}
|