2014-05-07 13:06:24 +08:00
|
|
|
|
package lea
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
|
|
|
|
"regexp"
|
|
|
|
|
"crypto/md5"
|
|
|
|
|
"crypto/rand"
|
|
|
|
|
"encoding/base64"
|
|
|
|
|
"encoding/hex"
|
|
|
|
|
"io"
|
2014-09-02 15:45:44 +08:00
|
|
|
|
"gopkg.in/mgo.v2/bson"
|
2014-05-07 13:06:24 +08:00
|
|
|
|
"time"
|
2015-06-15 18:01:48 +08:00
|
|
|
|
"strings"
|
2015-10-10 15:06:48 +08:00
|
|
|
|
"github.com/PuerkitoBio/goquery"
|
|
|
|
|
"bytes"
|
2014-05-07 13:06:24 +08:00
|
|
|
|
math_rand "math/rand"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// 字符串
|
|
|
|
|
|
|
|
|
|
// md5
|
|
|
|
|
func Md5(s string) string {
|
|
|
|
|
h := md5.New()
|
|
|
|
|
h.Write([]byte(s))
|
|
|
|
|
return hex.EncodeToString(h.Sum(nil))
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-10 14:12:22 +08:00
|
|
|
|
// 3位数的转换, 为了用bson.id -> 3位数
|
|
|
|
|
func Digest3(str string) string {
|
|
|
|
|
var b rune = 0
|
|
|
|
|
for _, k := range str {
|
|
|
|
|
b += k
|
|
|
|
|
}
|
|
|
|
|
return fmt.Sprintf("%d", b % 1000)
|
|
|
|
|
}
|
|
|
|
|
func Digest2(str string) string {
|
|
|
|
|
var b rune = 0
|
|
|
|
|
for _, k := range str {
|
|
|
|
|
b += k
|
|
|
|
|
}
|
|
|
|
|
return fmt.Sprintf("%d", b % 100)
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-07 13:06:24 +08:00
|
|
|
|
// Guid
|
|
|
|
|
func NewGuid() string {
|
|
|
|
|
b := make([]byte, 48)
|
|
|
|
|
|
|
|
|
|
if _, err := io.ReadFull(rand.Reader, b); err != nil {
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
return Md5(base64.URLEncoding.EncodeToString(b))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 后面加个str生成之, 更有保障, 确保唯一
|
|
|
|
|
func NewGuidWith(str string) string {
|
|
|
|
|
b := make([]byte, 48)
|
|
|
|
|
|
|
|
|
|
if _, err := io.ReadFull(rand.Reader, b); err != nil {
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
return Md5(base64.URLEncoding.EncodeToString([]byte(string(b) + str)))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 以byte来截取
|
|
|
|
|
func SubstringByte(str string, start int) string {
|
|
|
|
|
return substr(str, start, len(str)-start, false)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Substring(str string, start int) string {
|
|
|
|
|
return substr(str, start, len(str)-start, true)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Substr(str string, start, length int) string {
|
|
|
|
|
return substr(str, start, length, true)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func substr(str string, start, length int, isRune bool) string {
|
|
|
|
|
rs := []rune(str)
|
|
|
|
|
rs2 := []byte(str)
|
|
|
|
|
|
|
|
|
|
rl := len(rs)
|
|
|
|
|
if !isRune {
|
|
|
|
|
rl = len(rs2)
|
|
|
|
|
}
|
|
|
|
|
end := 0
|
|
|
|
|
|
|
|
|
|
if start < 0 {
|
|
|
|
|
start = rl - 1 + start
|
|
|
|
|
}
|
|
|
|
|
end = start + length
|
|
|
|
|
|
|
|
|
|
if start > end {
|
|
|
|
|
start, end = end, start
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if start < 0 {
|
|
|
|
|
start = 0
|
|
|
|
|
}
|
|
|
|
|
if start > rl {
|
|
|
|
|
start = rl
|
|
|
|
|
}
|
|
|
|
|
if end < 0 {
|
|
|
|
|
end = 0
|
|
|
|
|
}
|
|
|
|
|
if end > rl {
|
|
|
|
|
end = rl
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if isRune {
|
|
|
|
|
return string(rs[start:end])
|
|
|
|
|
}
|
|
|
|
|
return string(rs2[start:end])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 截取含html的字符串
|
|
|
|
|
/*
|
|
|
|
|
<div>
|
|
|
|
|
abcdef
|
|
|
|
|
<p>xxxxxxxxxxx</p>
|
|
|
|
|
<img src="" />
|
|
|
|
|
<div>
|
|
|
|
|
abcdfef
|
|
|
|
|
<p>aksdfjsld
|
|
|
|
|
dfsadf
|
|
|
|
|
--------------- 这里截断
|
|
|
|
|
</p>
|
|
|
|
|
<p>xxxxxxxxxxxxxxx</p>
|
|
|
|
|
abcdef
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
那么只要在最后的html中添加</p></div></div>补全结束即可
|
|
|
|
|
思路:
|
|
|
|
|
1. 找到截断的位置
|
|
|
|
|
2. 去掉成对的标签
|
|
|
|
|
3. 去掉不要结束的标签
|
|
|
|
|
4. 补全标签
|
|
|
|
|
*/
|
|
|
|
|
func ReplaceAll(oldStr, pattern, newStr string) string {
|
|
|
|
|
p, _ := regexp.Compile(pattern)
|
|
|
|
|
s := p.ReplaceAll([]byte(oldStr), []byte(newStr))
|
|
|
|
|
return string(s)
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-31 14:27:26 +08:00
|
|
|
|
// 获取纯文本
|
2015-10-10 15:06:48 +08:00
|
|
|
|
func SubStringHTMLToRaw(param string, length int) string {
|
2015-03-31 14:27:26 +08:00
|
|
|
|
if param == "" {
|
2015-10-10 15:06:48 +08:00
|
|
|
|
return param
|
2015-03-31 14:27:26 +08:00
|
|
|
|
}
|
|
|
|
|
n := 0
|
|
|
|
|
var temp rune // 中文问题, 用rune来解决
|
|
|
|
|
rStr := []rune(param)
|
2015-10-10 15:06:48 +08:00
|
|
|
|
lenStr := len(rStr)
|
2015-03-31 14:27:26 +08:00
|
|
|
|
isCode := false
|
2015-10-10 15:06:48 +08:00
|
|
|
|
|
|
|
|
|
resultRune := make([]rune, length)
|
|
|
|
|
// s := ""
|
|
|
|
|
for i := 0; i < lenStr; i++ {
|
2015-03-31 14:27:26 +08:00
|
|
|
|
temp = rStr[i]
|
|
|
|
|
if temp == '<' {
|
|
|
|
|
isCode = true
|
|
|
|
|
continue
|
|
|
|
|
} else if temp == '>' {
|
|
|
|
|
isCode = false
|
2015-10-10 15:06:48 +08:00
|
|
|
|
resultRune[n] = ' ';
|
|
|
|
|
|
|
|
|
|
n++
|
|
|
|
|
if n >= length {
|
|
|
|
|
break
|
|
|
|
|
}
|
2015-03-31 14:27:26 +08:00
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if !isCode {
|
2015-10-10 15:06:48 +08:00
|
|
|
|
resultRune[n] = temp;
|
|
|
|
|
// s += string(temp)
|
2015-03-31 14:27:26 +08:00
|
|
|
|
n++
|
|
|
|
|
if n >= length {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-10-10 15:06:48 +08:00
|
|
|
|
result := string(resultRune[0:n])
|
|
|
|
|
return strings.Trim(result, " ")
|
2015-03-31 14:27:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
2015-10-10 15:06:48 +08:00
|
|
|
|
// 自带方法补全html
|
|
|
|
|
func fixHtml(result string) string {
|
2014-05-07 13:06:24 +08:00
|
|
|
|
// 取出所有标签
|
|
|
|
|
tempResult := ReplaceAll(result, "(>)[^<>]*(<?)", "$1$2") // 把标签中间的所有内容都去掉了
|
|
|
|
|
|
|
|
|
|
// 2. 去掉不需要结素标记的HTML标记
|
|
|
|
|
tempResult = ReplaceAll(tempResult, "</?(embed|AREA|BASE|BASEFONT|BR|COL|COLGROUP|DD|DT|FRAME|HEAD|HR|IMG|INPUT|ISINDEX|LI|LINK|META|OPTION|PARAM|area|wbr|br|col|colgroup|dd|dt|frame|hr|img|input|isindex|link|meta|param)[^<>]*/?>", "")
|
|
|
|
|
|
|
|
|
|
// 把<div class=xxx的class=xxx去掉
|
|
|
|
|
tempResult = ReplaceAll(tempResult, "<(/?[a-zA-Z]+)[^<>]*>", "<$1>")
|
|
|
|
|
|
|
|
|
|
// 3 只能用正则,+stack来去有结束的
|
|
|
|
|
// golang的正则暂不支持back reference, 以后可以用它来去掉重复的标签
|
|
|
|
|
p, _ := regexp.Compile("<(/?[a-zA-Z]+)[^<>]*>") // 得到所有的<div>, </div>...
|
|
|
|
|
strs := p.FindAllString(tempResult, -1)
|
|
|
|
|
|
|
|
|
|
// fmt.Println(strs)
|
|
|
|
|
stack := make([]string, len(strs))
|
|
|
|
|
stackP := -1
|
|
|
|
|
for _, each := range strs {
|
|
|
|
|
if stackP >= 0 {
|
|
|
|
|
// 匹配
|
|
|
|
|
if stack[stackP][1:] == each[2:] {
|
|
|
|
|
stackP--
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
stackP++
|
|
|
|
|
stack[stackP] = each
|
|
|
|
|
}
|
|
|
|
|
// 补全tag
|
|
|
|
|
if stackP != -1 {
|
|
|
|
|
fmt.Println(stack[0 : stackP+1])
|
|
|
|
|
|
|
|
|
|
for _, each := range stack[0 : stackP+1] {
|
|
|
|
|
if each[1] != '/' {
|
|
|
|
|
result += "</" + each[1:]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
}
|
2015-03-31 14:27:26 +08:00
|
|
|
|
|
2015-10-10 15:06:48 +08:00
|
|
|
|
// 获取摘要, HTML
|
|
|
|
|
func SubStringHTML(param string, length int, end string) string {
|
|
|
|
|
if param == "" {
|
|
|
|
|
return param
|
|
|
|
|
}
|
|
|
|
|
result := ""
|
|
|
|
|
|
|
|
|
|
rStr := []rune(param)
|
|
|
|
|
lenStr := len(rStr)
|
|
|
|
|
|
|
|
|
|
if lenStr <= length {
|
|
|
|
|
result = param
|
|
|
|
|
} else {
|
|
|
|
|
// 1
|
|
|
|
|
n := 0
|
|
|
|
|
var temp rune // 中文问题, 用rune来解决
|
|
|
|
|
isCode := false //是不是HTML代码
|
|
|
|
|
isHTML := false //是不是HTML特殊字符,如
|
|
|
|
|
var i = 0;
|
|
|
|
|
for ; i < lenStr; i++ {
|
|
|
|
|
temp = rStr[i]
|
|
|
|
|
if temp == '<' {
|
|
|
|
|
isCode = true
|
|
|
|
|
} else if temp == '&' {
|
|
|
|
|
isHTML = true
|
|
|
|
|
} else if temp == '>' && isCode {
|
|
|
|
|
// n = n - 1
|
|
|
|
|
isCode = false
|
|
|
|
|
} else if temp == ';' && isHTML {
|
|
|
|
|
isHTML = false
|
|
|
|
|
}
|
|
|
|
|
if !isCode && !isHTML {
|
|
|
|
|
n = n + 1
|
|
|
|
|
}
|
|
|
|
|
// 每一次都相加, 速度非常慢!, 重新分配内存, 7倍的差距
|
|
|
|
|
// result += string(temp)
|
|
|
|
|
if n >= length {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result = string(rStr[0:i])
|
|
|
|
|
|
|
|
|
|
if end != "" {
|
|
|
|
|
result += end
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 使用goquery来取出html, 为了补全html
|
|
|
|
|
htmlReader := bytes.NewBufferString(result)
|
|
|
|
|
dom, err1 := goquery.NewDocumentFromReader(htmlReader)
|
|
|
|
|
if err1 == nil {
|
|
|
|
|
html, _ := dom.Html()
|
|
|
|
|
html = strings.Replace(html, "<html><head></head><body>", "", 1)
|
|
|
|
|
html = strings.Replace(html, "</body></html>", "", 1)
|
|
|
|
|
|
|
|
|
|
// TODO 把style="float: left"去掉
|
|
|
|
|
return html
|
|
|
|
|
|
|
|
|
|
// 如果有错误, 则使用自己的方法补全, 有风险
|
|
|
|
|
} else {
|
|
|
|
|
return fixHtml(result)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-07 13:06:24 +08:00
|
|
|
|
// 是否是合格的密码
|
|
|
|
|
func IsGoodPwd(pwd string) (bool, string) {
|
|
|
|
|
if pwd == "" {
|
|
|
|
|
return false, "密码不能为空"
|
|
|
|
|
}
|
|
|
|
|
if len(pwd) < 6 {
|
|
|
|
|
return false, "密码至少6位"
|
|
|
|
|
}
|
|
|
|
|
return true, ""
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 是否是email
|
|
|
|
|
func IsEmail(email string) bool {
|
|
|
|
|
if email == "" {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2015-10-10 15:02:55 +08:00
|
|
|
|
ok, _ := regexp.MatchString(`^([a-zA-Z0-9]+[_|\_|\.|\-]?)*[_a-z\-A-Z0-9]+@([a-zA-Z0-9]+[_|\_|\.|\-]?)*[a-zA-Z0-9\-]+\.[0-9a-zA-Z]{2,6}$`, email)
|
2014-05-07 13:06:24 +08:00
|
|
|
|
return ok
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 是否只包含数字, 字母 -, _
|
|
|
|
|
func IsUsername(username string) bool {
|
|
|
|
|
if username == "" {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
ok, _ := regexp.MatchString(`[^0-9a-zA-Z_\-]`, username)
|
|
|
|
|
return !ok
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 是否是ObjectId
|
|
|
|
|
func IsObjectId(id string) (ok bool) {
|
|
|
|
|
defer func() { // 必须要先声明defer,否则不能捕获到panic异常
|
|
|
|
|
// 证明有错误发生
|
|
|
|
|
if err := recover(); err != nil {
|
|
|
|
|
ok = false
|
|
|
|
|
} else {
|
|
|
|
|
ok = true
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
bson.ObjectIdHex(id)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 随机密码
|
|
|
|
|
// num 几位
|
|
|
|
|
func RandomPwd(num int) string {
|
|
|
|
|
chars := make([]byte, 62)
|
|
|
|
|
j := 0
|
|
|
|
|
for i := 48; i <= 57; i++ {
|
|
|
|
|
chars[j] = byte(i)
|
|
|
|
|
j++
|
|
|
|
|
}
|
|
|
|
|
for i := 65; i <= 90; i++ {
|
|
|
|
|
chars[j] = byte(i)
|
|
|
|
|
j++
|
|
|
|
|
}
|
|
|
|
|
for i := 97; i <= 122; i++ {
|
|
|
|
|
chars[j] = byte(i)
|
|
|
|
|
j++
|
|
|
|
|
}
|
|
|
|
|
j--;
|
|
|
|
|
|
|
|
|
|
str := ""
|
|
|
|
|
math_rand.Seed(time.Now().UnixNano())
|
|
|
|
|
for i := 0; i < num; i++ {
|
|
|
|
|
x := math_rand.Intn(j)
|
|
|
|
|
str += string(chars[x])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return str
|
2014-09-19 17:18:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func InArray(arr []string, str string) bool {
|
|
|
|
|
if arr == nil {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
for _, v := range arr {
|
|
|
|
|
if v == str {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false
|
2015-06-15 18:01:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 将名称的特殊字符去掉
|
|
|
|
|
func FixFilename(filename string) string {
|
|
|
|
|
if filename != "" {
|
|
|
|
|
// 把特殊字段给替换掉
|
|
|
|
|
// str := `life "%&()+,/:;<>=?@\|`
|
|
|
|
|
// . == \\.
|
|
|
|
|
// $ === \\$
|
|
|
|
|
reg, _ := regexp.Compile("\\.|/|#|\\$|!|\\^|\\*|'| |\"|%|&|\\(|\\)|\\+|\\,|/|:|;|<|>|=|\\?|@|\\||\\\\")
|
|
|
|
|
filename = reg.ReplaceAllString(filename, "-")
|
|
|
|
|
filename = strings.Trim(filename, "-") // 左右单独的-去掉
|
|
|
|
|
// 把空格替换成-
|
|
|
|
|
// filename = strings.Replace(filename, " ", "-", -1)
|
|
|
|
|
for strings.Index(filename, "--") >= 0 { // 防止出现连续的--
|
|
|
|
|
filename = strings.Replace(filename, "--", "-", -1)
|
|
|
|
|
}
|
|
|
|
|
return filename
|
|
|
|
|
}
|
|
|
|
|
return filename
|
|
|
|
|
}
|