|
|
@ -1,7 +1,9 @@ |
|
|
|
package validator |
|
|
|
package validator |
|
|
|
|
|
|
|
|
|
|
|
import ( |
|
|
|
import ( |
|
|
|
|
|
|
|
"bytes" |
|
|
|
"context" |
|
|
|
"context" |
|
|
|
|
|
|
|
"crypto/sha256" |
|
|
|
"fmt" |
|
|
|
"fmt" |
|
|
|
"net" |
|
|
|
"net" |
|
|
|
"net/url" |
|
|
|
"net/url" |
|
|
@ -11,8 +13,6 @@ import ( |
|
|
|
"sync" |
|
|
|
"sync" |
|
|
|
"time" |
|
|
|
"time" |
|
|
|
"unicode/utf8" |
|
|
|
"unicode/utf8" |
|
|
|
"crypto/sha256" |
|
|
|
|
|
|
|
"bytes" |
|
|
|
|
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
// Func accepts a FieldLevel interface for all validation needs. The return
|
|
|
|
// Func accepts a FieldLevel interface for all validation needs. The return
|
|
|
@ -187,7 +187,7 @@ func isOneOf(fl FieldLevel) bool { |
|
|
|
return false |
|
|
|
return false |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// isUnique is the validation function for validating if each array|slice element is unique
|
|
|
|
// isUnique is the validation function for validating if each array|slice|map value is unique
|
|
|
|
func isUnique(fl FieldLevel) bool { |
|
|
|
func isUnique(fl FieldLevel) bool { |
|
|
|
|
|
|
|
|
|
|
|
field := fl.Field() |
|
|
|
field := fl.Field() |
|
|
@ -195,12 +195,19 @@ func isUnique(fl FieldLevel) bool { |
|
|
|
|
|
|
|
|
|
|
|
switch field.Kind() { |
|
|
|
switch field.Kind() { |
|
|
|
case reflect.Slice, reflect.Array: |
|
|
|
case reflect.Slice, reflect.Array: |
|
|
|
m := reflect.MakeMap(reflect.MapOf(fl.Field().Type().Elem(), v.Type())) |
|
|
|
m := reflect.MakeMap(reflect.MapOf(field.Type().Elem(), v.Type())) |
|
|
|
|
|
|
|
|
|
|
|
for i := 0; i < field.Len(); i++ { |
|
|
|
for i := 0; i < field.Len(); i++ { |
|
|
|
m.SetMapIndex(field.Index(i), v) |
|
|
|
m.SetMapIndex(field.Index(i), v) |
|
|
|
} |
|
|
|
} |
|
|
|
return field.Len() == m.Len() |
|
|
|
return field.Len() == m.Len() |
|
|
|
|
|
|
|
case reflect.Map: |
|
|
|
|
|
|
|
m := reflect.MakeMap(reflect.MapOf(field.Type().Elem(), v.Type())) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for _, k := range field.MapKeys() { |
|
|
|
|
|
|
|
m.SetMapIndex(field.MapIndex(k), v) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return field.Len() == m.Len() |
|
|
|
default: |
|
|
|
default: |
|
|
|
panic(fmt.Sprintf("Bad field type %T", field.Interface())) |
|
|
|
panic(fmt.Sprintf("Bad field type %T", field.Interface())) |
|
|
|
} |
|
|
|
} |
|
|
@ -451,13 +458,13 @@ func isBitcoinAddress(fl FieldLevel) bool { |
|
|
|
func isBitcoinBech32Address(fl FieldLevel) bool { |
|
|
|
func isBitcoinBech32Address(fl FieldLevel) bool { |
|
|
|
address := fl.Field().String() |
|
|
|
address := fl.Field().String() |
|
|
|
|
|
|
|
|
|
|
|
if !btcLowerAddressRegexBech32.MatchString(address) && !btcUpperAddressRegexBech32.MatchString(address){ |
|
|
|
if !btcLowerAddressRegexBech32.MatchString(address) && !btcUpperAddressRegexBech32.MatchString(address) { |
|
|
|
return false |
|
|
|
return false |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
am := len(address) % 8 |
|
|
|
am := len(address) % 8 |
|
|
|
|
|
|
|
|
|
|
|
if am == 0 || am == 3 || am == 5{ |
|
|
|
if am == 0 || am == 3 || am == 5 { |
|
|
|
return false |
|
|
|
return false |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -474,7 +481,7 @@ func isBitcoinBech32Address(fl FieldLevel) bool { |
|
|
|
|
|
|
|
|
|
|
|
ver := dp[0] |
|
|
|
ver := dp[0] |
|
|
|
|
|
|
|
|
|
|
|
if ver < 0 || ver > 16{ |
|
|
|
if ver < 0 || ver > 16 { |
|
|
|
return false |
|
|
|
return false |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -486,16 +493,16 @@ func isBitcoinBech32Address(fl FieldLevel) bool { |
|
|
|
|
|
|
|
|
|
|
|
values := append(hr, dp...) |
|
|
|
values := append(hr, dp...) |
|
|
|
|
|
|
|
|
|
|
|
GEN := []int{ 0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3 } |
|
|
|
GEN := []int{0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3} |
|
|
|
|
|
|
|
|
|
|
|
p := 1 |
|
|
|
p := 1 |
|
|
|
|
|
|
|
|
|
|
|
for _, v := range values { |
|
|
|
for _, v := range values { |
|
|
|
b := p >> 25 |
|
|
|
b := p >> 25 |
|
|
|
p = (p & 0x1ffffff) << 5 ^ v |
|
|
|
p = (p&0x1ffffff)<<5 ^ v |
|
|
|
|
|
|
|
|
|
|
|
for i := 0; i < 5; i++ { |
|
|
|
for i := 0; i < 5; i++ { |
|
|
|
if (b >> uint(i)) & 1 == 1 { |
|
|
|
if (b>>uint(i))&1 == 1 { |
|
|
|
p ^= GEN[i] |
|
|
|
p ^= GEN[i] |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -510,16 +517,16 @@ func isBitcoinBech32Address(fl FieldLevel) bool { |
|
|
|
mv := (1 << 5) - 1 |
|
|
|
mv := (1 << 5) - 1 |
|
|
|
sw := []int{} |
|
|
|
sw := []int{} |
|
|
|
|
|
|
|
|
|
|
|
for _, v := range dp[1:len(dp) - 6]{ |
|
|
|
for _, v := range dp[1 : len(dp)-6] { |
|
|
|
acc = (acc << 5) | v |
|
|
|
acc = (acc << 5) | v |
|
|
|
b += 5 |
|
|
|
b += 5 |
|
|
|
for b >= 8{ |
|
|
|
for b >= 8 { |
|
|
|
b -= 8 |
|
|
|
b -= 8 |
|
|
|
sw = append(sw, (acc>>b)&mv) |
|
|
|
sw = append(sw, (acc>>b)&mv) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if len(sw) < 2 || len(sw) > 40{ |
|
|
|
if len(sw) < 2 || len(sw) > 40 { |
|
|
|
return false |
|
|
|
return false |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|