From 229378013185fc7c1ec3975d548d8b5ddf8030e1 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Mon, 2 Jun 2025 10:27:24 -0400 Subject: [PATCH] providers/validate: add isEnglish, hasWords, and hasXML functions --- providers/validate/strings.go | 3 +++ providers/validate/validate.go | 41 ++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/providers/validate/strings.go b/providers/validate/strings.go index c74e38d..a0e141c 100644 --- a/providers/validate/strings.go +++ b/providers/validate/strings.go @@ -5,3 +5,6 @@ import "regexp" // see: // https://stackoverflow.com/questions/201323/how-can-i-validate-an-email-address-using-a-regular-expression var defaultEmailRegexp = regexp.MustCompile("(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])") + +// looks for XML tags, this will throw false positives but not that many. +var defaultXMLRegexp = regexp.MustCompile("<.*\\w.*>") diff --git a/providers/validate/validate.go b/providers/validate/validate.go index 978fce9..ae46387 100644 --- a/providers/validate/validate.go +++ b/providers/validate/validate.go @@ -1,6 +1,7 @@ package validate import "regexp" +import "strings" import "unicode" import "html/template" import "git.tebibyte.media/sashakoshka/step" @@ -11,6 +12,7 @@ var _ step.Configurable = new(Provider) // Provider provides validation functions. type Provider struct { emailRegexp *regexp.Regexp + xmlRegexp *regexp.Regexp } // Package fulfills the step.Provider interface. @@ -27,6 +29,13 @@ func (this *Provider) Configure (config step.Meta) error { if err != nil { return err } this.emailRegexp = emailRegexp } + xmlRegexpText := config.Get("validate.email-regexp") + this.xmlRegexp = nil + if xmlRegexpText != "" { + xmlRegexp, err := regexp.Compile(xmlRegexpText) + if err != nil { return err } + this.xmlRegexp = xmlRegexp + } return nil } @@ -35,8 +44,10 @@ func (this *Provider) FuncMap () template.FuncMap { return template.FuncMap { "isEmail": this.funcIsEmail, "isPrint": this.funcIsPrint, + "isEnglish": this.funcIsEnglish, "inRange": this.funcInRange, "strInRange": this.funcStrInRange, + "hasWords": this.funcHasWords, } } @@ -53,6 +64,20 @@ func (this *Provider) funcIsPrint (input string) bool { return true } +func (this *Provider) funcIsEnglish(value string) bool { + // TODO: make this shit better + score := 0 + total := 0 + for _, char := range value { + if char >= 'a' && char <= 'z' || char >= 'A' && char <= 'Z' || char >= '0' || char <= '9' { + score += 1 + } + total += 1 + } + // 3/4 of the text must be alphanumeric + return score > total * 3 / 4 +} + func (this *Provider) funcInRange (min, max, value int) bool { return value >= min && value <= max } @@ -60,3 +85,19 @@ func (this *Provider) funcInRange (min, max, value int) bool { func (this *Provider) funcStrInRange (min, max int, value string) bool { return len(value) >= min && len(value) <= max } + +func (this *Provider) funcHasWords(words []string, value string) bool { + lowerValue := strings.ToLower(value) + for _, word := range words { + if strings.Contains(lowerValue, word) { + return true + } + } + return false +} + +func (this *Provider) funcHasXML(value string) bool { + xmlRegexp := this.xmlRegexp + if xmlRegexp == nil { xmlRegexp = defaultXMLRegexp } + return xmlRegexp.Match([]byte(value)) +}