mirror of
https://github.com/amir20/dozzle.git
synced 2026-08-07 10:04:45 +00:00
bd4651fb0b
Deploy VitePress site to Pages / build (push) Has been cancelled
Deploy VitePress site to Pages / Deploy (push) Has been cancelled
Push container / Push branches and PRs (push) Has been cancelled
Test / Typecheck (push) Has been cancelled
Test / JavaScript Tests (push) Has been cancelled
Test / Go Tests (push) Has been cancelled
Test / Go Staticcheck (push) Has been cancelled
Test / Integration Tests (push) Has been cancelled
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
127 lines
3.4 KiB
Go
127 lines
3.4 KiB
Go
package support_web
|
|
|
|
import (
|
|
"html"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/amir20/dozzle/internal/container"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
orderedmap "github.com/wk8/go-ordered-map/v2"
|
|
)
|
|
|
|
// URL marker regex compiled once for performance
|
|
var urlMarkerRegex = regexp.MustCompile(URLMarkerStart + "(.*?)" + URLMarkerEnd)
|
|
var searchMarkerStripper = strings.NewReplacer(MarkerStart, "", MarkerEnd, "")
|
|
var searchMarkerHTMLReplacer = strings.NewReplacer(MarkerStart, "<mark>", MarkerEnd, "</mark>")
|
|
|
|
func EscapeHTMLValues(logEvent *container.LogEvent) {
|
|
MarkURLs(logEvent)
|
|
|
|
switch value := logEvent.Message.(type) {
|
|
case string:
|
|
logEvent.Message = escapeAndProcessMarkers(value)
|
|
|
|
case []container.LogFragment:
|
|
for i, fragment := range value {
|
|
value[i].Message = escapeAndProcessMarkers(fragment.Message)
|
|
}
|
|
|
|
case *orderedmap.OrderedMap[string, any]:
|
|
escapeAnyMap(value)
|
|
|
|
case *orderedmap.OrderedMap[string, string]:
|
|
escapeStringMap(value)
|
|
|
|
case map[string]any:
|
|
panic("not implemented")
|
|
|
|
case map[string]string:
|
|
panic("not implemented")
|
|
|
|
default:
|
|
log.Trace().Type("type", value).Msg("unknown logEvent type")
|
|
}
|
|
}
|
|
|
|
func escapeAndProcessMarkers(value string) string {
|
|
value = html.EscapeString(value)
|
|
value = urlMarkerRegex.ReplaceAllStringFunc(value, func(match string) string {
|
|
url := strings.TrimSuffix(strings.TrimPrefix(match, URLMarkerStart), URLMarkerEnd)
|
|
href := searchMarkerStripper.Replace(url)
|
|
text := searchMarkerHTMLReplacer.Replace(url)
|
|
return "<a href=\"" + href + "\" target=\"_blank\" rel=\"noopener noreferrer external\">" + text + "</a>"
|
|
})
|
|
value = searchMarkerHTMLReplacer.Replace(value)
|
|
return value
|
|
}
|
|
|
|
func escapeAnyMap(orderedMap *orderedmap.OrderedMap[string, any]) {
|
|
for pair := orderedMap.Oldest(); pair != nil; pair = pair.Next() {
|
|
switch value := pair.Value.(type) {
|
|
case string:
|
|
orderedMap.Set(pair.Key, escapeAndProcessMarkers(value))
|
|
case *orderedmap.OrderedMap[string, any]:
|
|
escapeAnyMap(value)
|
|
case *orderedmap.OrderedMap[string, string]:
|
|
escapeStringMap(value)
|
|
case map[string]any:
|
|
escapeMapStringInterface(value)
|
|
case map[string]string:
|
|
escapeStringMapString(value)
|
|
case []any:
|
|
escapeSlice(value)
|
|
orderedMap.Set(pair.Key, value)
|
|
default:
|
|
log.Trace().Type("type", value).Msg("unknown logEvent type")
|
|
}
|
|
}
|
|
}
|
|
|
|
func escapeStringMap(orderedMap *orderedmap.OrderedMap[string, string]) {
|
|
for pair := orderedMap.Oldest(); pair != nil; pair = pair.Next() {
|
|
orderedMap.Set(pair.Key, escapeAndProcessMarkers(pair.Value))
|
|
}
|
|
}
|
|
|
|
func escapeMapStringInterface(value map[string]any) {
|
|
for key, val := range value {
|
|
switch val := val.(type) {
|
|
case string:
|
|
value[key] = escapeAndProcessMarkers(val)
|
|
case map[string]any:
|
|
escapeMapStringInterface(val)
|
|
case map[string]string:
|
|
escapeStringMapString(val)
|
|
case []any:
|
|
escapeSlice(val)
|
|
}
|
|
}
|
|
}
|
|
|
|
func escapeStringMapString(value map[string]string) {
|
|
for key, val := range value {
|
|
value[key] = escapeAndProcessMarkers(val)
|
|
}
|
|
}
|
|
|
|
func escapeSlice(slice []any) {
|
|
for i, val := range slice {
|
|
switch val := val.(type) {
|
|
case string:
|
|
slice[i] = escapeAndProcessMarkers(val)
|
|
case *orderedmap.OrderedMap[string, any]:
|
|
escapeAnyMap(val)
|
|
case *orderedmap.OrderedMap[string, string]:
|
|
escapeStringMap(val)
|
|
case map[string]any:
|
|
escapeMapStringInterface(val)
|
|
case map[string]string:
|
|
escapeStringMapString(val)
|
|
case []any:
|
|
escapeSlice(val)
|
|
}
|
|
}
|
|
}
|