This commit is contained in:
arraykeys
2019-08-08 17:13:34 +08:00
parent e8e5966a8c
commit f0bf2d5fec
2885 changed files with 1195993 additions and 12 deletions
+21
View File
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014 caixw
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -0,0 +1,8 @@
// Copyright 2014 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.
// 一些常用的验证函数
package validator
const Version = "0.1.0.140928"
@@ -0,0 +1,68 @@
// Copyright 2014 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.
package validator
// 我国现行的身份证号码有两种标准:GB11643-1989、GB11643-1999
//
// GB11643-1989为一代身份证,从左至右分别为:
// ------------------------------------------------------------
// | 6位行政区域代码 | 6位出生年日期(不含世纪数)| 3位顺序码 |
// ------------------------------------------------------------
//
// GB11643-1999为二代身份证,从左至右分别为:
// ------------------------------------------------------------
// | 6位行政区域代码 | 8位出生日期 | 3位顺序码 | 1位检验码 |
// ------------------------------------------------------------
var (
// 校验位对应的规则。
gb11643Map = []byte{'1', '0', 'x', '9', '8', '7', '6', '5', '4', '3', '2'}
// 前17位号码对应的权值,为一个固定数组。可由gb11643_test.getWeight()计算得到。
gb11643Weight = []int{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}
)
// 判断一个身份证是否符合gb11643标准。
// 若是15位则当作一代身份证,仅简单地判断各位是否都是数字;
// 若是18位则当作二代身份证,会计算校验位是否正确;
// 其它位数都返回false。
func IsGb11643(val interface{}) bool {
switch v := val.(type) {
case string:
return IsGb11643Bytes([]byte(v))
case []byte:
return IsGb11643Bytes(v)
case []rune:
return IsGb11643Bytes([]byte(string(v)))
default:
return false
}
}
// 判断一个身份证是否符合gb11643标准。
func IsGb11643Bytes(val []byte) bool {
if len(val) == 15 {
// 15位,只检测是否包含非数字字符。
for i := 0; i < 15; i++ {
if val[i] < '0' || val[i] > '9' {
return false
}
} // end for
return true
}
if len(val) != 18 {
return false
}
sum := 0
for i := 0; i < 17; i++ {
sum += (gb11643Weight[i] * int((val[i] - '0')))
}
if val[17] == 'X' {
val[17] = 'x'
}
return gb11643Map[sum%11] == val[17]
}
@@ -0,0 +1,99 @@
// Copyright 2014 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.
package validator
import (
"bytes"
)
// 有关ISBN的算法及其它相关内容,可参照http://zh.wikipedia.org/wiki/%E5%9B%BD%E9%99%85%E6%A0%87%E5%87%86%E4%B9%A6%E5%8F%B7
// 判断是否为合法的ISBN串号。可以同时判断ISBN10和ISBN13
func IsISBN(val interface{}) bool {
var result []byte
switch v := val.(type) {
case []byte:
result = v
case []rune:
result = []byte(string(v))
case string:
result = []byte(v)
default:
return false
}
if bytes.IndexByte(result, '-') > -1 {
result = eraseMinus(result)
}
switch len(result) {
case 10:
return isISBN10(result)
case 13:
return isISBN13(result)
default:
return false
}
}
// 判断是否为合法的ISBN10
func IsISBN10(val []byte) bool {
if bytes.IndexByte(val, '-') == -1 {
return isISBN10(val)
}
return isISBN10(eraseMinus(val))
}
// 判断是否为合法的ISBN13
func IsISBN13(val []byte) bool {
if bytes.IndexByte(val, '-') == -1 {
return isISBN13(val)
}
return isISBN13(eraseMinus(val))
}
// isbn10的校验位对应的值。
var isbn10Map = []byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'x', '0'}
func isISBN10(val []byte) bool {
sum := 0
for i := 0; i < 9; i++ {
sum += int(val[i]-'0') * (10 - i)
}
if val[9] == 'X' {
val[9] = 'x'
}
return isbn10Map[11-sum%11] == val[9]
}
func isISBN13(val []byte) bool {
sum := 0
for i := 0; i < 12; i += 2 {
sum += int(val[i] - '0')
}
for i := 1; i < 12; i += 2 {
sum += (int(val[i]-'0') * 3)
}
return (10 - sum%10) == int(val[12]-'0')
}
// 过滤减号(-)符号
func eraseMinus(val []byte) []byte {
offset := 0
for k, v := range val {
if v == '-' {
offset += 1
continue
}
val[k-offset] = v
}
return val[0 : len(val)-offset]
}
@@ -0,0 +1,123 @@
// Copyright 2014 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.
package validator
import (
"regexp"
)
const (
// 匹配大陆电话
cnPhoneStr = `((\d{3,4})-?)?` + // 区号
`\d{7,8}` + // 号码
`(-\d{1,4})?` // 分机号,分机号的连接符号不能省略。
// 匹配大陆手机号码
cnMobileStr = `(0|\+?86)?` + // 匹配 0,86,+86
`(13[0-9]|` + // 130-139
`14[57]|` + // 145,147
`15[0-35-9]|` + // 150-153,155-159
`17[0678]|` + // 170,176,177,17u
`18[0-9])` + // 180-189
`[0-9]{8}`
// 匹配邮箱
emailStr = `[\w.-]+@[\w_-]+\w{1,}[\.\w-]+`
// 匹配IP4
ip4Str = `((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)`
// 匹配IP6,参考以下网页内容:
// http://blog.csdn.net/jiangfeng08/article/details/7642018
ip6Str = `(([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|` +
`(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|` +
`(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|` +
`(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|` +
`(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|` +
`(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|` +
`(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|` +
`(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))`
// 同时匹配IP4和IP6
ipStr = "(" + ip4Str + ")|(" + ip6Str + ")"
// 匹配域名
domainStr = `[a-zA-Z0-9][a-zA-Z0-9_-]{0,62}(\.[a-zA-Z0-9][a-zA-Z0-9_-]{0,62})*(\.[a-zA-Z][a-zA-Z0-9]{0,10}){1}`
// 匹配URL
urlStr = `((https|http|ftp|rtsp|mms)?://)?` + // 协议
`(([0-9a-zA-Z]+:)?[0-9a-zA-Z_-]+@)?` + // pwd:user@
"(" + ipStr + "|(" + domainStr + "))" + // IP或域名
`(:\d{1,4})?` + // 端口
`(/+[a-zA-Z0-9][a-zA-Z0-9_.-]*/*)*` + // path
`(\?([a-zA-Z0-9_-]+(=[a-zA-Z0-9_-]*)*)*)*` // query
)
func regexpCompile(str string) *regexp.Regexp {
return regexp.MustCompile("^" + str + "$")
}
var (
email = regexpCompile(emailStr)
ip4 = regexpCompile(ip4Str)
ip6 = regexpCompile(ip6Str)
ip = regexpCompile(ipStr)
url = regexpCompile(urlStr)
cnPhone = regexpCompile(cnPhoneStr)
cnMobile = regexpCompile(cnMobileStr)
)
// 判断val是否能正确匹配exp中的正则表达式。
// val可以是[]byte, []rune, string类型。
func isMatch(exp *regexp.Regexp, val interface{}) bool {
switch v := val.(type) {
case []rune:
return exp.MatchString(string(v))
case []byte:
return exp.Match(v)
case string:
return exp.MatchString(v)
default:
return false
}
}
// 验证中国大陆的电话号码。支持如下格式:
// 0578-12345678-1234
// 057812345678-1234
// 若存在分机号,则分机号的连接符不能省略。
func IsCnPhone(val interface{}) bool {
return isMatch(cnPhone, val)
}
// 验证中国大陆的手机号码
func IsCnMobile(val interface{}) bool {
return isMatch(cnMobile, val)
}
// 验证一个值是否标准的URL格式。支持IP和域名等格式
func IsURL(val interface{}) bool {
return isMatch(url, val)
}
// 验证一个值是否为IP,可验证IP4和IP6
func IsIP(val interface{}) bool {
return isMatch(ip, val)
}
// 验证一个值是否为IP6
func IsIP6(val interface{}) bool {
return isMatch(ip6, val)
}
// 验证一个值是滞为IP4
func IsIP4(val interface{}) bool {
return isMatch(ip4, val)
}
// 验证一个值是否匹配一个邮箱。
func IsEmail(val interface{}) bool {
return isMatch(email, val)
}
@@ -0,0 +1,60 @@
// Copyright 2014 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.
package validator
import (
"github.com/caixw/lib.go/assert"
)
// 判断一个[]byte变量是否可以转换成数值。
func IsNumberBytes(bs []byte) bool {
// 首位字符可以是[0-9.+-]
b := bs[0]
if (b < '0' && b > '9') && b != '+' && b != '-' && b != '.' {
return false
}
hasDot := (b == '.')
for _, b = range bs[1:] {
if (b < '0' || b > '9') && b != '.' {
return false
}
if b == '.' {
if hasDot { // 多个小数点
return false
}
hasDot = true
}
}
return true
}
// 判断一个值是否可转换为数值。不支持全角数值的判断。
// 允许带一个小数点及起始的正负号,但不允许千位分隔符什么的。
func IsNumber(val interface{}) bool {
switch v := val.(type) {
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64:
return true
case []byte:
return IsNumberBytes(v)
case string:
return IsNumberBytes([]byte(v))
default:
return false
}
}
// 判断是否为空值。
// 具体参照githbu.com/caixw/lib.go/assert.IsEmtpy()
func IsEmpty(val interface{}) bool {
return assert.IsEmpty(val)
}
// 判断是否为Nil。
// 具体参照githbu.com/caixw/lib.go/assert.IsNil()
func IsNil(val interface{}) bool {
return assert.IsNil(val)
}