From d5ea2aa824eee4b7e2d169d21da0107d057e7bc6 Mon Sep 17 00:00:00 2001 From: Bobby <30593201+luciferreeves@users.noreply.github.com> Date: Wed, 24 Dec 2025 17:17:15 +0530 Subject: feat: Implement API endpoints for email details and actions, and refactor email preview for client-side rendering with Shadow DOM. --- utils/format/date.go | 5 ----- utils/format/html.go | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++ utils/format/size.go | 16 ++++++++++++++ 3 files changed, 75 insertions(+), 5 deletions(-) create mode 100644 utils/format/size.go (limited to 'utils/format') diff --git a/utils/format/date.go b/utils/format/date.go index 8ef95cb..a326fa0 100644 --- a/utils/format/date.go +++ b/utils/format/date.go @@ -1,7 +1,6 @@ package format import ( - "html" "lain/types" "time" ) @@ -93,7 +92,3 @@ func formatTime(date time.Time, timeFormat types.TimeFormat) string { return date.Format("15:04") } } - -func DecodeHTML(text string) string { - return html.UnescapeString(text) -} diff --git a/utils/format/html.go b/utils/format/html.go index 36e2425..d976cb8 100644 --- a/utils/format/html.go +++ b/utils/format/html.go @@ -1,10 +1,65 @@ package format import ( + "html" "regexp" "strings" ) +func SanitizeHTML(htmlContent string) string { + // Remove dangerous tags + htmlContent = removeDangerousTags(htmlContent) + + // Remove inline event handlers + htmlContent = removeEventHandlers(htmlContent) + + // Remove javascript: protocol + htmlContent = removeJavascriptProtocol(htmlContent) + + // Sanitize styles + htmlContent = sanitizeStyles(htmlContent) + + return htmlContent +} + +func removeDangerousTags(html string) string { + dangerousTags := []string{ + "script", "iframe", "object", "embed", "applet", + "meta", "link", "base", "form", "input", "button", + } + + for _, tag := range dangerousTags { + regex := regexp.MustCompile(`(?i)<` + tag + `[^>]*>[\s\S]*?`) + html = regex.ReplaceAllString(html, "") + regex = regexp.MustCompile(`(?i)<` + tag + `[^>]*>`) + html = regex.ReplaceAllString(html, "") + } + + return html +} + +func removeEventHandlers(html string) string { + eventHandlers := regexp.MustCompile(`(?i)\s*on\w+\s*=\s*["'][^"']*["']`) + return eventHandlers.ReplaceAllString(html, "") +} + +func removeJavascriptProtocol(html string) string { + jsProtocol := regexp.MustCompile(`(?i)javascript:`) + return jsProtocol.ReplaceAllString(html, "") +} + +func sanitizeStyles(html string) string { + // Remove dangerous CSS properties + dangerousStyles := []string{"behavior", "expression", "binding", "import", "moz-binding"} + + for _, style := range dangerousStyles { + regex := regexp.MustCompile(`(?i)` + style + `\s*:\s*[^;]+;?`) + html = regex.ReplaceAllString(html, "") + } + + return html +} + func GenerateSnippet(bodyText, bodyHTML string) string { text := bodyText if text == "" && bodyHTML != "" { @@ -71,3 +126,7 @@ func StripHTML(html string) string { return strings.TrimSpace(strings.Join(cleanLines, " ")) } + +func DecodeHTML(text string) string { + return html.UnescapeString(text) +} diff --git a/utils/format/size.go b/utils/format/size.go new file mode 100644 index 0000000..ce7c4fa --- /dev/null +++ b/utils/format/size.go @@ -0,0 +1,16 @@ +package format + +import "fmt" + +func FormatFileSize(bytes int64) string { + const unit = 1024 + if bytes < unit { + return fmt.Sprintf("%d B", bytes) + } + div, exp := int64(unit), 0 + for n := bytes / unit; n >= unit; n /= unit { + div *= unit + exp++ + } + return fmt.Sprintf("%.1f %cB", float64(bytes)/float64(div), "KMGTPE"[exp]) +} -- cgit v1.2.3