From 0a9b75fbfdb5730dfff911981b428046167f33e6 Mon Sep 17 00:00:00 2001 From: heatwole Date: Thu, 28 Jun 2018 18:11:36 -0500 Subject: [PATCH] Adding html and url encoding and updating docs --- baked_in.go | 15 ++++++ doc.go | 21 ++++++++ regexes.go | 6 +++ validator_test.go | 123 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 165 insertions(+) diff --git a/baked_in.go b/baked_in.go index 3f87da4..ad1db78 100644 --- a/baked_in.go +++ b/baked_in.go @@ -144,6 +144,9 @@ var ( "fqdn": isFQDN, "unique": isUnique, "oneof": isOneOf, + "html": isHTML, + "html_encoded": isHTMLEncoded, + "url_encoded": isURLEncoded, } ) @@ -163,6 +166,18 @@ func parseOneOfParam2(s string) []string { return vals } +func isURLEncoded(fl FieldLevel) bool { + return uRLEncodedRegex.MatchString(fl.Field().String()) +} + +func isHTMLEncoded(fl FieldLevel) bool { + return hTMLEncodedRegex.MatchString(fl.Field().String()) +} + +func isHTML(fl FieldLevel) bool { + return hTMLRegex.MatchString(fl.Field().String()) +} + func isOneOf(fl FieldLevel) bool { vals := parseOneOfParam2(fl.Param()) diff --git a/doc.go b/doc.go index be93d79..1163749 100644 --- a/doc.go +++ b/doc.go @@ -895,6 +895,27 @@ This validates that a string value contains a valid FQDN. Usage: fqdn +HTML Tags + +This validates that a string value appears to be an HTML element tag +including those described at https://developer.mozilla.org/en-US/docs/Web/HTML/Element + + Usage: html + +HTML Encoded + +This validates that a string value is a proper character reference in decimal +or hexadecimal format + + Usage: html_encoded + +URL Encoded + +This validates that a string value is percent-encoded (URL encoded) according +to https://tools.ietf.org/html/rfc3986#section-2.1 + + Usage: url_encoded + Alias Validators and Tags NOTE: When returning an error, the tag returned in "FieldError" will be diff --git a/regexes.go b/regexes.go index 131df4c..07a8705 100644 --- a/regexes.go +++ b/regexes.go @@ -39,6 +39,9 @@ const ( ethAddressRegexString = `^0x[0-9a-fA-F]{40}$` ethAddressUpperRegexString = `^0x[0-9A-F]{40}$` ethAddressLowerRegexString = `^0x[0-9a-f]{40}$` + uRLEncodedRegexString = `(%[A-Fa-f0-9]{2})` + hTMLEncodedRegexString = `&#[x]?([0-9a-fA-F]{2})|(>)|(<)|(")|(&)+[;]?` + hTMLRegexString = `<[/]?([a-zA-Z]+).*?>` ) var ( @@ -78,4 +81,7 @@ var ( ethAddressRegex = regexp.MustCompile(ethAddressRegexString) ethaddressRegexUpper = regexp.MustCompile(ethAddressUpperRegexString) ethAddressRegexLower = regexp.MustCompile(ethAddressLowerRegexString) + uRLEncodedRegex = regexp.MustCompile(uRLEncodedRegexString) + hTMLEncodedRegex = regexp.MustCompile(hTMLEncodedRegexString) + hTMLRegex = regexp.MustCompile(hTMLRegexString) ) diff --git a/validator_test.go b/validator_test.go index 0823812..b488cf8 100644 --- a/validator_test.go +++ b/validator_test.go @@ -7758,6 +7758,129 @@ func TestUniqueValidation(t *testing.T) { PanicMatches(t, func() { validate.Var(1.0, "unique") }, "Bad field type float64") } +func TestHTMLValidation(t *testing.T) { + tests := []struct { + param string + expected bool + }{ + {"", true}, + {"", true}, + {"", false}, + {"<123nonsense>", false}, + {"test", false}, + {"&example", false}, + } + + validate := New() + + for i, test := range tests { + + errs := validate.Var(test.param, "html") + + if test.expected { + if !IsEqual(errs, nil) { + t.Fatalf("Index: %d html failed Error: %v", i, errs) + } + } else { + if IsEqual(errs, nil) { + t.Fatalf("Index: %d html failed Error: %v", i, errs) + } else { + val := getError(errs, "", "") + if val.Tag() != "html" { + t.Fatalf("Index: %d html failed Error: %v", i, errs) + } + } + } + } +} + +func TestHTMLEncodedValidation(t *testing.T) { + tests := []struct { + param string + expected bool + }{ + {"<", true}, + {"¯", true}, + {"�", true}, + {"ð", true}, + {"<", true}, + {"¯", true}, + {"�", true}, + {"ð", true}, + {"&#ab", true}, + {"<", true}, + {">", true}, + {""", true}, + {"&", true}, + {"#x0a", false}, + {"&x00", false}, + {"z", false}, + } + + validate := New() + + for i, test := range tests { + + errs := validate.Var(test.param, "html_encoded") + + if test.expected { + if !IsEqual(errs, nil) { + t.Fatalf("Index: %d html_encoded failed Error: %v", i, errs) + } + } else { + if IsEqual(errs, nil) { + t.Fatalf("Index: %d html_enocded failed Error: %v", i, errs) + } else { + val := getError(errs, "", "") + if val.Tag() != "html_encoded" { + t.Fatalf("Index: %d html_encoded failed Error: %v", i, errs) + } + } + } + } +} + +func TestURLEncodedValidation(t *testing.T) { + tests := []struct { + param string + expected bool + }{ + {"%20", true}, + {"%af", true}, + {"%ff", true}, + {"<%az", false}, + {"%test%", false}, + {"a%b", false}, + {"1%2", false}, + {"%%a%%", false}, + } + + validate := New() + + for i, test := range tests { + + errs := validate.Var(test.param, "url_encoded") + + if test.expected { + if !IsEqual(errs, nil) { + t.Fatalf("Index: %d url_encoded failed Error: %v", i, errs) + } + } else { + if IsEqual(errs, nil) { + t.Fatalf("Index: %d url_enocded failed Error: %v", i, errs) + } else { + val := getError(errs, "", "") + if val.Tag() != "url_encoded" { + t.Fatalf("Index: %d url_encoded failed Error: %v", i, errs) + } + } + } + } +} + func TestKeys(t *testing.T) { type Test struct {