package utils import ( "html" "regexp" "strings" "unicode/utf8" ) // Sanitizer provides input sanitization utilities type Sanitizer struct { // Max lengths for common fields MaxNameLength int MaxDescriptionLength int MaxEmailLength int } // DefaultSanitizer returns a sanitizer with default settings func DefaultSanitizer() *Sanitizer { return &Sanitizer{ MaxNameLength: 255, MaxDescriptionLength: 10000, MaxEmailLength: 320, } } // SanitizeString escapes HTML and trims whitespace func (s *Sanitizer) SanitizeString(input string) string { if input == "" { return "" } // Trim whitespace result := strings.TrimSpace(input) // Escape HTML entities to prevent XSS result = html.EscapeString(result) return result } // SanitizeName sanitizes a name field func (s *Sanitizer) SanitizeName(input string) string { sanitized := s.SanitizeString(input) if utf8.RuneCountInString(sanitized) > s.MaxNameLength { runes := []rune(sanitized) sanitized = string(runes[:s.MaxNameLength]) } return sanitized } // SanitizeEmail sanitizes and validates email format func (s *Sanitizer) SanitizeEmail(input string) string { sanitized := strings.TrimSpace(strings.ToLower(input)) if utf8.RuneCountInString(sanitized) > s.MaxEmailLength { return "" } return sanitized } // SanitizeDescription sanitizes long text fields func (s *Sanitizer) SanitizeDescription(input string) string { sanitized := s.SanitizeString(input) if utf8.RuneCountInString(sanitized) > s.MaxDescriptionLength { runes := []rune(sanitized) sanitized = string(runes[:s.MaxDescriptionLength]) } return sanitized } // SanitizeSlug creates a URL-safe slug func (s *Sanitizer) SanitizeSlug(input string) string { // Convert to lowercase result := strings.ToLower(strings.TrimSpace(input)) // Replace spaces with hyphens result = strings.ReplaceAll(result, " ", "-") // Remove non-alphanumeric characters except hyphens reg := regexp.MustCompile(`[^a-z0-9-]`) result = reg.ReplaceAllString(result, "") // Remove multiple consecutive hyphens reg = regexp.MustCompile(`-+`) result = reg.ReplaceAllString(result, "-") // Trim hyphens from ends result = strings.Trim(result, "-") return result } // StripHTML removes all HTML tags from input func StripHTML(input string) string { reg := regexp.MustCompile(`<[^>]*>`) return reg.ReplaceAllString(input, "") } // SanitizePhone cleans a phone number, keeping only digits and an optional // leading '+' (international dialing prefix). Removes all formatting characters // such as spaces, dashes, parentheses, and dots. // // Examples: // // "+55 (11) 99999-8888" → "+5511999998888" // "(11) 99999-8888" → "11999998888" // "+1-800-555-0100" → "+18005550100" func SanitizePhone(phone string) string { phone = strings.TrimSpace(phone) if phone == "" { return "" } hasPlus := strings.HasPrefix(phone, "+") digitsOnly := regexp.MustCompile(`\D`).ReplaceAllString(phone, "") if hasPlus { return "+" + digitsOnly } return digitsOnly }