Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
B
beego
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
beego
Commits
19119e99
Commit
19119e99
authored
Dec 12, 2013
by
astaxie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
move utils to utils libs & func move to templatefunc
parent
d603a671
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
555 additions
and
591 deletions
+555
-591
controller.go
controller.go
+13
-1
router.go
router.go
+5
-4
template.go
template.go
+3
-155
templatefunc.go
templatefunc.go
+509
-409
templatefunc_test.go
templatefunc_test.go
+0
-22
slice.go
utils/slice.go
+10
-0
slice_test.go
utils/slice_test.go
+15
-0
No files found.
controller.go
View file @
19119e99
...
...
@@ -3,6 +3,7 @@ package beego
import
(
"bytes"
"crypto/hmac"
"crypto/rand"
"crypto/sha1"
"encoding/base64"
"errors"
...
...
@@ -370,7 +371,7 @@ func (c *Controller) XsrfToken() string {
}
else
{
expire
=
int64
(
XSRFExpire
)
}
token
=
G
etRandomString
(
15
)
token
=
g
etRandomString
(
15
)
c
.
SetSecureCookie
(
XSRFKEY
,
"_xsrf"
,
token
,
expire
)
}
c
.
_xsrf_token
=
token
...
...
@@ -405,3 +406,14 @@ func (c *Controller) GoToFunc(funcname string) {
}
c
.
gotofunc
=
funcname
}
//utils func for controller internal
func
getRandomString
(
n
int
)
string
{
const
alphanum
=
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
var
bytes
=
make
([]
byte
,
n
)
rand
.
Read
(
bytes
)
for
i
,
b
:=
range
bytes
{
bytes
[
i
]
=
alphanum
[
b
%
byte
(
len
(
alphanum
))]
}
return
string
(
bytes
)
}
router.go
View file @
19119e99
...
...
@@ -15,6 +15,7 @@ import (
beecontext
"github.com/astaxie/beego/context"
"github.com/astaxie/beego/middleware"
"github.com/astaxie/beego/toolbox"
"github.com/astaxie/beego/utils"
)
const
(
...
...
@@ -159,7 +160,7 @@ func (p *ControllerRegistor) Add(pattern string, c ControllerInterface, mappingM
}
comma
:=
strings
.
Split
(
colon
[
0
],
","
)
for
_
,
m
:=
range
comma
{
if
m
==
"*"
||
i
nSlice
(
strings
.
ToLower
(
m
),
HTTPMETHOD
)
{
if
m
==
"*"
||
utils
.
I
nSlice
(
strings
.
ToLower
(
m
),
HTTPMETHOD
)
{
if
val
:=
reflectVal
.
MethodByName
(
colon
[
1
]);
val
.
IsValid
()
{
methods
[
strings
.
ToLower
(
m
)]
=
colon
[
1
]
}
else
{
...
...
@@ -272,7 +273,7 @@ func (p *ControllerRegistor) UrlFor(endpoint string, values ...string) string {
for
_
,
route
:=
range
p
.
fixrouters
{
if
route
.
controllerType
.
Name
()
==
controllName
{
var
finded
bool
if
i
nSlice
(
strings
.
ToLower
(
methodName
),
HTTPMETHOD
)
{
if
utils
.
I
nSlice
(
strings
.
ToLower
(
methodName
),
HTTPMETHOD
)
{
if
route
.
hasMethod
{
if
m
,
ok
:=
route
.
methods
[
strings
.
ToLower
(
methodName
)];
ok
&&
m
!=
methodName
{
finded
=
false
...
...
@@ -303,7 +304,7 @@ func (p *ControllerRegistor) UrlFor(endpoint string, values ...string) string {
for
_
,
route
:=
range
p
.
routers
{
if
route
.
controllerType
.
Name
()
==
controllName
{
var
finded
bool
if
i
nSlice
(
strings
.
ToLower
(
methodName
),
HTTPMETHOD
)
{
if
utils
.
I
nSlice
(
strings
.
ToLower
(
methodName
),
HTTPMETHOD
)
{
if
route
.
hasMethod
{
if
m
,
ok
:=
route
.
methods
[
strings
.
ToLower
(
methodName
)];
ok
&&
m
!=
methodName
{
finded
=
false
...
...
@@ -419,7 +420,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
context
.
Output
=
beecontext
.
NewOutput
(
rw
)
}
if
!
i
nSlice
(
strings
.
ToLower
(
r
.
Method
),
HTTPMETHOD
)
{
if
!
utils
.
I
nSlice
(
strings
.
ToLower
(
r
.
Method
),
HTTPMETHOD
)
{
http
.
Error
(
w
,
"Method Not Allowed"
,
405
)
goto
Admin
}
...
...
template.go
View file @
19119e99
...
...
@@ -9,9 +9,10 @@ import (
"io/ioutil"
"os"
"path/filepath"
"reflect"
"regexp"
"strings"
"github.com/astaxie/beego/utils"
)
var
(
...
...
@@ -144,7 +145,7 @@ func getTplDeep(root, file, parent string, t *template.Template) (*template.Temp
}
else
{
fileabspath
=
filepath
.
Join
(
root
,
file
)
}
if
e
,
_
:=
FileExists
(
fileabspath
);
!
e
{
if
e
:=
utils
.
FileExists
(
fileabspath
);
!
e
{
panic
(
"can't find template file"
+
file
)
}
data
,
err
:=
ioutil
.
ReadFile
(
fileabspath
)
...
...
@@ -238,156 +239,3 @@ func _getTemplate(t0 *template.Template, root string, submods [][]string, others
}
return
}
// go1.2 added template funcs. begin
var
(
errBadComparisonType
=
errors
.
New
(
"invalid type for comparison"
)
errBadComparison
=
errors
.
New
(
"incompatible types for comparison"
)
errNoComparison
=
errors
.
New
(
"missing argument for comparison"
)
)
type
kind
int
const
(
invalidKind
kind
=
iota
boolKind
complexKind
intKind
floatKind
integerKind
stringKind
uintKind
)
func
basicKind
(
v
reflect
.
Value
)
(
kind
,
error
)
{
switch
v
.
Kind
()
{
case
reflect
.
Bool
:
return
boolKind
,
nil
case
reflect
.
Int
,
reflect
.
Int8
,
reflect
.
Int16
,
reflect
.
Int32
,
reflect
.
Int64
:
return
intKind
,
nil
case
reflect
.
Uint
,
reflect
.
Uint8
,
reflect
.
Uint16
,
reflect
.
Uint32
,
reflect
.
Uint64
,
reflect
.
Uintptr
:
return
uintKind
,
nil
case
reflect
.
Float32
,
reflect
.
Float64
:
return
floatKind
,
nil
case
reflect
.
Complex64
,
reflect
.
Complex128
:
return
complexKind
,
nil
case
reflect
.
String
:
return
stringKind
,
nil
}
return
invalidKind
,
errBadComparisonType
}
// eq evaluates the comparison a == b || a == c || ...
func
eq
(
arg1
interface
{},
arg2
...
interface
{})
(
bool
,
error
)
{
v1
:=
reflect
.
ValueOf
(
arg1
)
k1
,
err
:=
basicKind
(
v1
)
if
err
!=
nil
{
return
false
,
err
}
if
len
(
arg2
)
==
0
{
return
false
,
errNoComparison
}
for
_
,
arg
:=
range
arg2
{
v2
:=
reflect
.
ValueOf
(
arg
)
k2
,
err
:=
basicKind
(
v2
)
if
err
!=
nil
{
return
false
,
err
}
if
k1
!=
k2
{
return
false
,
errBadComparison
}
truth
:=
false
switch
k1
{
case
boolKind
:
truth
=
v1
.
Bool
()
==
v2
.
Bool
()
case
complexKind
:
truth
=
v1
.
Complex
()
==
v2
.
Complex
()
case
floatKind
:
truth
=
v1
.
Float
()
==
v2
.
Float
()
case
intKind
:
truth
=
v1
.
Int
()
==
v2
.
Int
()
case
stringKind
:
truth
=
v1
.
String
()
==
v2
.
String
()
case
uintKind
:
truth
=
v1
.
Uint
()
==
v2
.
Uint
()
default
:
panic
(
"invalid kind"
)
}
if
truth
{
return
true
,
nil
}
}
return
false
,
nil
}
// ne evaluates the comparison a != b.
func
ne
(
arg1
,
arg2
interface
{})
(
bool
,
error
)
{
// != is the inverse of ==.
equal
,
err
:=
eq
(
arg1
,
arg2
)
return
!
equal
,
err
}
// lt evaluates the comparison a < b.
func
lt
(
arg1
,
arg2
interface
{})
(
bool
,
error
)
{
v1
:=
reflect
.
ValueOf
(
arg1
)
k1
,
err
:=
basicKind
(
v1
)
if
err
!=
nil
{
return
false
,
err
}
v2
:=
reflect
.
ValueOf
(
arg2
)
k2
,
err
:=
basicKind
(
v2
)
if
err
!=
nil
{
return
false
,
err
}
if
k1
!=
k2
{
return
false
,
errBadComparison
}
truth
:=
false
switch
k1
{
case
boolKind
,
complexKind
:
return
false
,
errBadComparisonType
case
floatKind
:
truth
=
v1
.
Float
()
<
v2
.
Float
()
case
intKind
:
truth
=
v1
.
Int
()
<
v2
.
Int
()
case
stringKind
:
truth
=
v1
.
String
()
<
v2
.
String
()
case
uintKind
:
truth
=
v1
.
Uint
()
<
v2
.
Uint
()
default
:
panic
(
"invalid kind"
)
}
return
truth
,
nil
}
// le evaluates the comparison <= b.
func
le
(
arg1
,
arg2
interface
{})
(
bool
,
error
)
{
// <= is < or ==.
lessThan
,
err
:=
lt
(
arg1
,
arg2
)
if
lessThan
||
err
!=
nil
{
return
lessThan
,
err
}
return
eq
(
arg1
,
arg2
)
}
// gt evaluates the comparison a > b.
func
gt
(
arg1
,
arg2
interface
{})
(
bool
,
error
)
{
// > is the inverse of <=.
lessOrEqual
,
err
:=
le
(
arg1
,
arg2
)
if
err
!=
nil
{
return
false
,
err
}
return
!
lessOrEqual
,
nil
}
// ge evaluates the comparison a >= b.
func
ge
(
arg1
,
arg2
interface
{})
(
bool
,
error
)
{
// >= is the inverse of <.
lessThan
,
err
:=
lt
(
arg1
,
arg2
)
if
err
!=
nil
{
return
false
,
err
}
return
!
lessThan
,
nil
}
// go1.2 added template funcs. end
utils
.go
→
templatefunc
.go
View file @
19119e99
package
beego
import
(
"crypto/rand"
"fmt"
"html/template"
"net/url"
"os"
"reflect"
"regexp"
"strconv"
"strings"
"time"
)
func
webTime
(
t
time
.
Time
)
string
{
ftime
:=
t
.
Format
(
time
.
RFC1123
)
if
strings
.
HasSuffix
(
ftime
,
"UTC"
)
{
ftime
=
ftime
[
0
:
len
(
ftime
)
-
3
]
+
"GMT"
}
return
ftime
}
func
Substr
(
s
string
,
start
,
length
int
)
string
{
bt
:=
[]
rune
(
s
)
if
start
<
0
{
start
=
0
}
var
end
int
if
(
start
+
length
)
>
(
len
(
bt
)
-
1
)
{
end
=
len
(
bt
)
}
else
{
end
=
start
+
length
}
return
string
(
bt
[
start
:
end
])
}
// Html2str() returns escaping text convert from html
func
Html2str
(
html
string
)
string
{
src
:=
string
(
html
)
//将HTML标签全转换成小写
re
,
_
:=
regexp
.
Compile
(
"
\\
<[
\\
S
\\
s]+?
\\
>"
)
src
=
re
.
ReplaceAllStringFunc
(
src
,
strings
.
ToLower
)
//去除STYLE
re
,
_
=
regexp
.
Compile
(
"
\\
<style[
\\
S
\\
s]+?
\\
</style
\\
>"
)
src
=
re
.
ReplaceAllString
(
src
,
""
)
//去除SCRIPT
re
,
_
=
regexp
.
Compile
(
"
\\
<script[
\\
S
\\
s]+?
\\
</script
\\
>"
)
src
=
re
.
ReplaceAllString
(
src
,
""
)
//去除所有尖括号内的HTML代码,并换成换行符
re
,
_
=
regexp
.
Compile
(
"
\\
<[
\\
S
\\
s]+?
\\
>"
)
src
=
re
.
ReplaceAllString
(
src
,
"
\n
"
)
//去除连续的换行符
re
,
_
=
regexp
.
Compile
(
"
\\
s{2,}"
)
src
=
re
.
ReplaceAllString
(
src
,
"
\n
"
)
return
strings
.
TrimSpace
(
src
)
}
// DateFormat takes a time and a layout string and returns a string with the formatted date. Used by the template parser as "dateformat"
func
DateFormat
(
t
time
.
Time
,
layout
string
)
(
datestring
string
)
{
datestring
=
t
.
Format
(
layout
)
return
}
var
DatePatterns
=
[]
string
{
// year
"Y"
,
"2006"
,
// A full numeric representation of a year, 4 digits Examples: 1999 or 2003
"y"
,
"06"
,
//A two digit representation of a year Examples: 99 or 03
// month
"m"
,
"01"
,
// Numeric representation of a month, with leading zeros 01 through 12
"n"
,
"1"
,
// Numeric representation of a month, without leading zeros 1 through 12
"M"
,
"Jan"
,
// A short textual representation of a month, three letters Jan through Dec
"F"
,
"January"
,
// A full textual representation of a month, such as January or March January through December
// day
"d"
,
"02"
,
// Day of the month, 2 digits with leading zeros 01 to 31
"j"
,
"2"
,
// Day of the month without leading zeros 1 to 31
// week
"D"
,
"Mon"
,
// A textual representation of a day, three letters Mon through Sun
"l"
,
"Monday"
,
// A full textual representation of the day of the week Sunday through Saturday
// time
"g"
,
"3"
,
// 12-hour format of an hour without leading zeros 1 through 12
"G"
,
"15"
,
// 24-hour format of an hour without leading zeros 0 through 23
"h"
,
"03"
,
// 12-hour format of an hour with leading zeros 01 through 12
"H"
,
"15"
,
// 24-hour format of an hour with leading zeros 00 through 23
"a"
,
"pm"
,
// Lowercase Ante meridiem and Post meridiem am or pm
"A"
,
"PM"
,
// Uppercase Ante meridiem and Post meridiem AM or PM
"i"
,
"04"
,
// Minutes with leading zeros 00 to 59
"s"
,
"05"
,
// Seconds, with leading zeros 00 through 59
// time zone
"T"
,
"MST"
,
"P"
,
"-07:00"
,
"O"
,
"-0700"
,
// RFC 2822
"r"
,
time
.
RFC1123Z
,
}
// Parse Date use PHP time format
func
DateParse
(
dateString
,
format
string
)
(
time
.
Time
,
error
)
{
replacer
:=
strings
.
NewReplacer
(
DatePatterns
...
)
format
=
replacer
.
Replace
(
format
)
return
time
.
ParseInLocation
(
format
,
dateString
,
time
.
Local
)
}
// Date takes a PHP like date func to Go's time format
func
Date
(
t
time
.
Time
,
format
string
)
string
{
replacer
:=
strings
.
NewReplacer
(
DatePatterns
...
)
format
=
replacer
.
Replace
(
format
)
return
t
.
Format
(
format
)
}
// Compare is a quick and dirty comparison function. It will convert whatever you give it to strings and see if the two values are equal.
// Whitespace is trimmed. Used by the template parser as "eq"
func
Compare
(
a
,
b
interface
{})
(
equal
bool
)
{
equal
=
false
if
strings
.
TrimSpace
(
fmt
.
Sprintf
(
"%v"
,
a
))
==
strings
.
TrimSpace
(
fmt
.
Sprintf
(
"%v"
,
b
))
{
equal
=
true
}
return
}
func
Str2html
(
raw
string
)
template
.
HTML
{
return
template
.
HTML
(
raw
)
}
func
Htmlquote
(
src
string
)
string
{
//HTML编码为实体符号
/*
Encodes `text` for raw use in HTML.
>>> htmlquote("<'&\\">")
'<'&">'
*/
text
:=
string
(
src
)
text
=
strings
.
Replace
(
text
,
"&"
,
"&"
,
-
1
)
// Must be done first!
text
=
strings
.
Replace
(
text
,
"<"
,
"<"
,
-
1
)
text
=
strings
.
Replace
(
text
,
">"
,
">"
,
-
1
)
text
=
strings
.
Replace
(
text
,
"'"
,
"'"
,
-
1
)
text
=
strings
.
Replace
(
text
,
"
\"
"
,
"""
,
-
1
)
text
=
strings
.
Replace
(
text
,
"“"
,
"“"
,
-
1
)
text
=
strings
.
Replace
(
text
,
"”"
,
"”"
,
-
1
)
text
=
strings
.
Replace
(
text
,
" "
,
" "
,
-
1
)
return
strings
.
TrimSpace
(
text
)
}
func
Htmlunquote
(
src
string
)
string
{
//实体符号解释为HTML
/*
Decodes `text` that's HTML quoted.
>>> htmlunquote('<'&">')
'<\\'&">'
*/
// strings.Replace(s, old, new, n)
// 在s字符串中,把old字符串替换为new字符串,n表示替换的次数,小于0表示全部替换
text
:=
string
(
src
)
text
=
strings
.
Replace
(
text
,
" "
,
" "
,
-
1
)
text
=
strings
.
Replace
(
text
,
"”"
,
"”"
,
-
1
)
text
=
strings
.
Replace
(
text
,
"“"
,
"“"
,
-
1
)
text
=
strings
.
Replace
(
text
,
"""
,
"
\"
"
,
-
1
)
text
=
strings
.
Replace
(
text
,
"'"
,
"'"
,
-
1
)
text
=
strings
.
Replace
(
text
,
">"
,
">"
,
-
1
)
text
=
strings
.
Replace
(
text
,
"<"
,
"<"
,
-
1
)
text
=
strings
.
Replace
(
text
,
"&"
,
"&"
,
-
1
)
// Must be done last!
return
strings
.
TrimSpace
(
text
)
}
func
inSlice
(
v
string
,
sl
[]
string
)
bool
{
for
_
,
vv
:=
range
sl
{
if
vv
==
v
{
return
true
}
}
return
false
}
// parse form values to struct via tag
func
ParseForm
(
form
url
.
Values
,
obj
interface
{})
error
{
objT
:=
reflect
.
TypeOf
(
obj
)
objV
:=
reflect
.
ValueOf
(
obj
)
if
!
isStructPtr
(
objT
)
{
return
fmt
.
Errorf
(
"%v must be a struct pointer"
,
obj
)
}
objT
=
objT
.
Elem
()
objV
=
objV
.
Elem
()
for
i
:=
0
;
i
<
objT
.
NumField
();
i
++
{
fieldV
:=
objV
.
Field
(
i
)
if
!
fieldV
.
CanSet
()
{
continue
}
fieldT
:=
objT
.
Field
(
i
)
tags
:=
strings
.
Split
(
fieldT
.
Tag
.
Get
(
"form"
),
","
)
var
tag
string
if
len
(
tags
)
==
0
||
len
(
tags
[
0
])
==
0
{
tag
=
fieldT
.
Name
}
else
if
tags
[
0
]
==
"-"
{
continue
}
else
{
tag
=
tags
[
0
]
}
value
:=
form
.
Get
(
tag
)
if
len
(
value
)
==
0
{
continue
}
switch
fieldT
.
Type
.
Kind
()
{
case
reflect
.
Bool
:
b
,
err
:=
strconv
.
ParseBool
(
value
)
if
err
!=
nil
{
return
err
}
fieldV
.
SetBool
(
b
)
case
reflect
.
Int
,
reflect
.
Int8
,
reflect
.
Int16
,
reflect
.
Int32
,
reflect
.
Int64
:
x
,
err
:=
strconv
.
ParseInt
(
value
,
10
,
64
)
if
err
!=
nil
{
return
err
}
fieldV
.
SetInt
(
x
)
case
reflect
.
Uint
,
reflect
.
Uint8
,
reflect
.
Uint16
,
reflect
.
Uint32
,
reflect
.
Uint64
:
x
,
err
:=
strconv
.
ParseUint
(
value
,
10
,
64
)
if
err
!=
nil
{
return
err
}
fieldV
.
SetUint
(
x
)
case
reflect
.
Float32
,
reflect
.
Float64
:
x
,
err
:=
strconv
.
ParseFloat
(
value
,
64
)
if
err
!=
nil
{
return
err
}
fieldV
.
SetFloat
(
x
)
case
reflect
.
Interface
:
fieldV
.
Set
(
reflect
.
ValueOf
(
value
))
case
reflect
.
String
:
fieldV
.
SetString
(
value
)
}
}
return
nil
}
// form types for RenderForm function
var
FormType
=
map
[
string
]
bool
{
"text"
:
true
,
"textarea"
:
true
,
"hidden"
:
true
,
"password"
:
true
,
}
var
unKind
=
map
[
reflect
.
Kind
]
bool
{
reflect
.
Uintptr
:
true
,
reflect
.
Complex64
:
true
,
reflect
.
Complex128
:
true
,
reflect
.
Array
:
true
,
reflect
.
Chan
:
true
,
reflect
.
Func
:
true
,
reflect
.
Map
:
true
,
reflect
.
Ptr
:
true
,
reflect
.
Slice
:
true
,
reflect
.
Struct
:
true
,
reflect
.
UnsafePointer
:
true
,
}
// obj must be a struct pointer
func
RenderForm
(
obj
interface
{})
template
.
HTML
{
objT
:=
reflect
.
TypeOf
(
obj
)
objV
:=
reflect
.
ValueOf
(
obj
)
if
!
isStructPtr
(
objT
)
{
return
template
.
HTML
(
""
)
}
objT
=
objT
.
Elem
()
objV
=
objV
.
Elem
()
var
raw
[]
string
for
i
:=
0
;
i
<
objT
.
NumField
();
i
++
{
fieldV
:=
objV
.
Field
(
i
)
if
!
fieldV
.
CanSet
()
||
unKind
[
fieldV
.
Kind
()]
{
continue
}
fieldT
:=
objT
.
Field
(
i
)
tags
:=
strings
.
Split
(
fieldT
.
Tag
.
Get
(
"form"
),
","
)
label
:=
fieldT
.
Name
+
": "
name
:=
fieldT
.
Name
fType
:=
"text"
switch
len
(
tags
)
{
case
1
:
if
tags
[
0
]
==
"-"
{
continue
}
if
len
(
tags
[
0
])
>
0
{
name
=
tags
[
0
]
}
case
2
:
if
len
(
tags
[
0
])
>
0
{
name
=
tags
[
0
]
}
if
len
(
tags
[
1
])
>
0
{
fType
=
tags
[
1
]
}
case
3
:
if
len
(
tags
[
0
])
>
0
{
name
=
tags
[
0
]
}
if
len
(
tags
[
1
])
>
0
{
fType
=
tags
[
1
]
}
if
len
(
tags
[
2
])
>
0
{
label
=
tags
[
2
]
}
}
raw
=
append
(
raw
,
fmt
.
Sprintf
(
`%v<input name="%v" type="%v" value="%v">`
,
label
,
name
,
fType
,
fieldV
.
Interface
()))
}
return
template
.
HTML
(
strings
.
Join
(
raw
,
"</br>"
))
}
func
isStructPtr
(
t
reflect
.
Type
)
bool
{
return
t
.
Kind
()
==
reflect
.
Ptr
&&
t
.
Elem
()
.
Kind
()
==
reflect
.
Struct
}
func
stringsToJson
(
str
string
)
string
{
rs
:=
[]
rune
(
str
)
jsons
:=
""
for
_
,
r
:=
range
rs
{
rint
:=
int
(
r
)
if
rint
<
128
{
jsons
+=
string
(
r
)
}
else
{
jsons
+=
"
\\
u"
+
strconv
.
FormatInt
(
int64
(
rint
),
16
)
// json
}
}
return
jsons
}
func
FileExists
(
path
string
)
(
bool
,
error
)
{
_
,
err
:=
os
.
Stat
(
path
)
if
err
==
nil
{
return
true
,
nil
}
if
os
.
IsNotExist
(
err
)
{
return
false
,
nil
}
return
false
,
err
}
func
GetRandomString
(
n
int
)
string
{
const
alphanum
=
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
var
bytes
=
make
([]
byte
,
n
)
rand
.
Read
(
bytes
)
for
i
,
b
:=
range
bytes
{
bytes
[
i
]
=
alphanum
[
b
%
byte
(
len
(
alphanum
))]
}
return
string
(
bytes
)
}
// This will reference the index function local to the current blueprint:
// UrlFor(".index")
// ... print UrlFor("index")
// ... print UrlFor("login")
// ... print UrlFor("login", "next","/"")
// ... print UrlFor("profile", "username","John Doe")
// ...
// /
// /login
// /login?next=/
// /user/John%20Doe
func
UrlFor
(
endpoint
string
,
values
...
string
)
string
{
return
BeeApp
.
UrlFor
(
endpoint
,
values
...
)
}
//This can be changed to a better name
func
AssetsJs
(
src
string
)
template
.
HTML
{
text
:=
string
(
src
)
text
=
"<script src=
\"
"
+
src
+
"
\"
></script>"
return
template
.
HTML
(
text
)
}
//This can be changed to a better name
func
AssetsCss
(
src
string
)
template
.
HTML
{
text
:=
string
(
src
)
text
=
"<link href=
\"
"
+
src
+
"
\"
rel=
\"
stylesheet
\"
/>"
return
template
.
HTML
(
text
)
}
package
beego
import
(
"errors"
"fmt"
"html/template"
"net/url"
"reflect"
"regexp"
"strconv"
"strings"
"time"
)
// Substr() return the substr from start to length
func
Substr
(
s
string
,
start
,
length
int
)
string
{
bt
:=
[]
rune
(
s
)
if
start
<
0
{
start
=
0
}
var
end
int
if
(
start
+
length
)
>
(
len
(
bt
)
-
1
)
{
end
=
len
(
bt
)
}
else
{
end
=
start
+
length
}
return
string
(
bt
[
start
:
end
])
}
// Html2str() returns escaping text convert from html
func
Html2str
(
html
string
)
string
{
src
:=
string
(
html
)
//将HTML标签全转换成小写
re
,
_
:=
regexp
.
Compile
(
"
\\
<[
\\
S
\\
s]+?
\\
>"
)
src
=
re
.
ReplaceAllStringFunc
(
src
,
strings
.
ToLower
)
//去除STYLE
re
,
_
=
regexp
.
Compile
(
"
\\
<style[
\\
S
\\
s]+?
\\
</style
\\
>"
)
src
=
re
.
ReplaceAllString
(
src
,
""
)
//去除SCRIPT
re
,
_
=
regexp
.
Compile
(
"
\\
<script[
\\
S
\\
s]+?
\\
</script
\\
>"
)
src
=
re
.
ReplaceAllString
(
src
,
""
)
//去除所有尖括号内的HTML代码,并换成换行符
re
,
_
=
regexp
.
Compile
(
"
\\
<[
\\
S
\\
s]+?
\\
>"
)
src
=
re
.
ReplaceAllString
(
src
,
"
\n
"
)
//去除连续的换行符
re
,
_
=
regexp
.
Compile
(
"
\\
s{2,}"
)
src
=
re
.
ReplaceAllString
(
src
,
"
\n
"
)
return
strings
.
TrimSpace
(
src
)
}
// DateFormat takes a time and a layout string and returns a string with the formatted date. Used by the template parser as "dateformat"
func
DateFormat
(
t
time
.
Time
,
layout
string
)
(
datestring
string
)
{
datestring
=
t
.
Format
(
layout
)
return
}
var
DatePatterns
=
[]
string
{
// year
"Y"
,
"2006"
,
// A full numeric representation of a year, 4 digits Examples: 1999 or 2003
"y"
,
"06"
,
//A two digit representation of a year Examples: 99 or 03
// month
"m"
,
"01"
,
// Numeric representation of a month, with leading zeros 01 through 12
"n"
,
"1"
,
// Numeric representation of a month, without leading zeros 1 through 12
"M"
,
"Jan"
,
// A short textual representation of a month, three letters Jan through Dec
"F"
,
"January"
,
// A full textual representation of a month, such as January or March January through December
// day
"d"
,
"02"
,
// Day of the month, 2 digits with leading zeros 01 to 31
"j"
,
"2"
,
// Day of the month without leading zeros 1 to 31
// week
"D"
,
"Mon"
,
// A textual representation of a day, three letters Mon through Sun
"l"
,
"Monday"
,
// A full textual representation of the day of the week Sunday through Saturday
// time
"g"
,
"3"
,
// 12-hour format of an hour without leading zeros 1 through 12
"G"
,
"15"
,
// 24-hour format of an hour without leading zeros 0 through 23
"h"
,
"03"
,
// 12-hour format of an hour with leading zeros 01 through 12
"H"
,
"15"
,
// 24-hour format of an hour with leading zeros 00 through 23
"a"
,
"pm"
,
// Lowercase Ante meridiem and Post meridiem am or pm
"A"
,
"PM"
,
// Uppercase Ante meridiem and Post meridiem AM or PM
"i"
,
"04"
,
// Minutes with leading zeros 00 to 59
"s"
,
"05"
,
// Seconds, with leading zeros 00 through 59
// time zone
"T"
,
"MST"
,
"P"
,
"-07:00"
,
"O"
,
"-0700"
,
// RFC 2822
"r"
,
time
.
RFC1123Z
,
}
// Parse Date use PHP time format
func
DateParse
(
dateString
,
format
string
)
(
time
.
Time
,
error
)
{
replacer
:=
strings
.
NewReplacer
(
DatePatterns
...
)
format
=
replacer
.
Replace
(
format
)
return
time
.
ParseInLocation
(
format
,
dateString
,
time
.
Local
)
}
// Date takes a PHP like date func to Go's time format
func
Date
(
t
time
.
Time
,
format
string
)
string
{
replacer
:=
strings
.
NewReplacer
(
DatePatterns
...
)
format
=
replacer
.
Replace
(
format
)
return
t
.
Format
(
format
)
}
// Compare is a quick and dirty comparison function. It will convert whatever you give it to strings and see if the two values are equal.
// Whitespace is trimmed. Used by the template parser as "eq"
func
Compare
(
a
,
b
interface
{})
(
equal
bool
)
{
equal
=
false
if
strings
.
TrimSpace
(
fmt
.
Sprintf
(
"%v"
,
a
))
==
strings
.
TrimSpace
(
fmt
.
Sprintf
(
"%v"
,
b
))
{
equal
=
true
}
return
}
func
Str2html
(
raw
string
)
template
.
HTML
{
return
template
.
HTML
(
raw
)
}
func
Htmlquote
(
src
string
)
string
{
//HTML编码为实体符号
/*
Encodes `text` for raw use in HTML.
>>> htmlquote("<'&\\">")
'<'&">'
*/
text
:=
string
(
src
)
text
=
strings
.
Replace
(
text
,
"&"
,
"&"
,
-
1
)
// Must be done first!
text
=
strings
.
Replace
(
text
,
"<"
,
"<"
,
-
1
)
text
=
strings
.
Replace
(
text
,
">"
,
">"
,
-
1
)
text
=
strings
.
Replace
(
text
,
"'"
,
"'"
,
-
1
)
text
=
strings
.
Replace
(
text
,
"
\"
"
,
"""
,
-
1
)
text
=
strings
.
Replace
(
text
,
"“"
,
"“"
,
-
1
)
text
=
strings
.
Replace
(
text
,
"”"
,
"”"
,
-
1
)
text
=
strings
.
Replace
(
text
,
" "
,
" "
,
-
1
)
return
strings
.
TrimSpace
(
text
)
}
func
Htmlunquote
(
src
string
)
string
{
//实体符号解释为HTML
/*
Decodes `text` that's HTML quoted.
>>> htmlunquote('<'&">')
'<\\'&">'
*/
// strings.Replace(s, old, new, n)
// 在s字符串中,把old字符串替换为new字符串,n表示替换的次数,小于0表示全部替换
text
:=
string
(
src
)
text
=
strings
.
Replace
(
text
,
" "
,
" "
,
-
1
)
text
=
strings
.
Replace
(
text
,
"”"
,
"”"
,
-
1
)
text
=
strings
.
Replace
(
text
,
"“"
,
"“"
,
-
1
)
text
=
strings
.
Replace
(
text
,
"""
,
"
\"
"
,
-
1
)
text
=
strings
.
Replace
(
text
,
"'"
,
"'"
,
-
1
)
text
=
strings
.
Replace
(
text
,
">"
,
">"
,
-
1
)
text
=
strings
.
Replace
(
text
,
"<"
,
"<"
,
-
1
)
text
=
strings
.
Replace
(
text
,
"&"
,
"&"
,
-
1
)
// Must be done last!
return
strings
.
TrimSpace
(
text
)
}
// This will reference the index function local to the current blueprint:
// UrlFor(".index")
// ... print UrlFor("index")
// ... print UrlFor("login")
// ... print UrlFor("login", "next","/"")
// ... print UrlFor("profile", "username","John Doe")
// ...
// /
// /login
// /login?next=/
// /user/John%20Doe
func
UrlFor
(
endpoint
string
,
values
...
string
)
string
{
return
BeeApp
.
UrlFor
(
endpoint
,
values
...
)
}
//This can be changed to a better name
func
AssetsJs
(
src
string
)
template
.
HTML
{
text
:=
string
(
src
)
text
=
"<script src=
\"
"
+
src
+
"
\"
></script>"
return
template
.
HTML
(
text
)
}
//This can be changed to a better name
func
AssetsCss
(
src
string
)
template
.
HTML
{
text
:=
string
(
src
)
text
=
"<link href=
\"
"
+
src
+
"
\"
rel=
\"
stylesheet
\"
/>"
return
template
.
HTML
(
text
)
}
// parse form values to struct via tag
func
ParseForm
(
form
url
.
Values
,
obj
interface
{})
error
{
objT
:=
reflect
.
TypeOf
(
obj
)
objV
:=
reflect
.
ValueOf
(
obj
)
if
!
isStructPtr
(
objT
)
{
return
fmt
.
Errorf
(
"%v must be a struct pointer"
,
obj
)
}
objT
=
objT
.
Elem
()
objV
=
objV
.
Elem
()
for
i
:=
0
;
i
<
objT
.
NumField
();
i
++
{
fieldV
:=
objV
.
Field
(
i
)
if
!
fieldV
.
CanSet
()
{
continue
}
fieldT
:=
objT
.
Field
(
i
)
tags
:=
strings
.
Split
(
fieldT
.
Tag
.
Get
(
"form"
),
","
)
var
tag
string
if
len
(
tags
)
==
0
||
len
(
tags
[
0
])
==
0
{
tag
=
fieldT
.
Name
}
else
if
tags
[
0
]
==
"-"
{
continue
}
else
{
tag
=
tags
[
0
]
}
value
:=
form
.
Get
(
tag
)
if
len
(
value
)
==
0
{
continue
}
switch
fieldT
.
Type
.
Kind
()
{
case
reflect
.
Bool
:
b
,
err
:=
strconv
.
ParseBool
(
value
)
if
err
!=
nil
{
return
err
}
fieldV
.
SetBool
(
b
)
case
reflect
.
Int
,
reflect
.
Int8
,
reflect
.
Int16
,
reflect
.
Int32
,
reflect
.
Int64
:
x
,
err
:=
strconv
.
ParseInt
(
value
,
10
,
64
)
if
err
!=
nil
{
return
err
}
fieldV
.
SetInt
(
x
)
case
reflect
.
Uint
,
reflect
.
Uint8
,
reflect
.
Uint16
,
reflect
.
Uint32
,
reflect
.
Uint64
:
x
,
err
:=
strconv
.
ParseUint
(
value
,
10
,
64
)
if
err
!=
nil
{
return
err
}
fieldV
.
SetUint
(
x
)
case
reflect
.
Float32
,
reflect
.
Float64
:
x
,
err
:=
strconv
.
ParseFloat
(
value
,
64
)
if
err
!=
nil
{
return
err
}
fieldV
.
SetFloat
(
x
)
case
reflect
.
Interface
:
fieldV
.
Set
(
reflect
.
ValueOf
(
value
))
case
reflect
.
String
:
fieldV
.
SetString
(
value
)
}
}
return
nil
}
// form types for RenderForm function
var
FormType
=
map
[
string
]
bool
{
"text"
:
true
,
"textarea"
:
true
,
"hidden"
:
true
,
"password"
:
true
,
}
var
unKind
=
map
[
reflect
.
Kind
]
bool
{
reflect
.
Uintptr
:
true
,
reflect
.
Complex64
:
true
,
reflect
.
Complex128
:
true
,
reflect
.
Array
:
true
,
reflect
.
Chan
:
true
,
reflect
.
Func
:
true
,
reflect
.
Map
:
true
,
reflect
.
Ptr
:
true
,
reflect
.
Slice
:
true
,
reflect
.
Struct
:
true
,
reflect
.
UnsafePointer
:
true
,
}
// obj must be a struct pointer
func
RenderForm
(
obj
interface
{})
template
.
HTML
{
objT
:=
reflect
.
TypeOf
(
obj
)
objV
:=
reflect
.
ValueOf
(
obj
)
if
!
isStructPtr
(
objT
)
{
return
template
.
HTML
(
""
)
}
objT
=
objT
.
Elem
()
objV
=
objV
.
Elem
()
var
raw
[]
string
for
i
:=
0
;
i
<
objT
.
NumField
();
i
++
{
fieldV
:=
objV
.
Field
(
i
)
if
!
fieldV
.
CanSet
()
||
unKind
[
fieldV
.
Kind
()]
{
continue
}
fieldT
:=
objT
.
Field
(
i
)
tags
:=
strings
.
Split
(
fieldT
.
Tag
.
Get
(
"form"
),
","
)
label
:=
fieldT
.
Name
+
": "
name
:=
fieldT
.
Name
fType
:=
"text"
switch
len
(
tags
)
{
case
1
:
if
tags
[
0
]
==
"-"
{
continue
}
if
len
(
tags
[
0
])
>
0
{
name
=
tags
[
0
]
}
case
2
:
if
len
(
tags
[
0
])
>
0
{
name
=
tags
[
0
]
}
if
len
(
tags
[
1
])
>
0
{
fType
=
tags
[
1
]
}
case
3
:
if
len
(
tags
[
0
])
>
0
{
name
=
tags
[
0
]
}
if
len
(
tags
[
1
])
>
0
{
fType
=
tags
[
1
]
}
if
len
(
tags
[
2
])
>
0
{
label
=
tags
[
2
]
}
}
raw
=
append
(
raw
,
fmt
.
Sprintf
(
`%v<input name="%v" type="%v" value="%v">`
,
label
,
name
,
fType
,
fieldV
.
Interface
()))
}
return
template
.
HTML
(
strings
.
Join
(
raw
,
"</br>"
))
}
func
isStructPtr
(
t
reflect
.
Type
)
bool
{
return
t
.
Kind
()
==
reflect
.
Ptr
&&
t
.
Elem
()
.
Kind
()
==
reflect
.
Struct
}
// go1.2 added template funcs. begin
var
(
errBadComparisonType
=
errors
.
New
(
"invalid type for comparison"
)
errBadComparison
=
errors
.
New
(
"incompatible types for comparison"
)
errNoComparison
=
errors
.
New
(
"missing argument for comparison"
)
)
type
kind
int
const
(
invalidKind
kind
=
iota
boolKind
complexKind
intKind
floatKind
integerKind
stringKind
uintKind
)
func
basicKind
(
v
reflect
.
Value
)
(
kind
,
error
)
{
switch
v
.
Kind
()
{
case
reflect
.
Bool
:
return
boolKind
,
nil
case
reflect
.
Int
,
reflect
.
Int8
,
reflect
.
Int16
,
reflect
.
Int32
,
reflect
.
Int64
:
return
intKind
,
nil
case
reflect
.
Uint
,
reflect
.
Uint8
,
reflect
.
Uint16
,
reflect
.
Uint32
,
reflect
.
Uint64
,
reflect
.
Uintptr
:
return
uintKind
,
nil
case
reflect
.
Float32
,
reflect
.
Float64
:
return
floatKind
,
nil
case
reflect
.
Complex64
,
reflect
.
Complex128
:
return
complexKind
,
nil
case
reflect
.
String
:
return
stringKind
,
nil
}
return
invalidKind
,
errBadComparisonType
}
// eq evaluates the comparison a == b || a == c || ...
func
eq
(
arg1
interface
{},
arg2
...
interface
{})
(
bool
,
error
)
{
v1
:=
reflect
.
ValueOf
(
arg1
)
k1
,
err
:=
basicKind
(
v1
)
if
err
!=
nil
{
return
false
,
err
}
if
len
(
arg2
)
==
0
{
return
false
,
errNoComparison
}
for
_
,
arg
:=
range
arg2
{
v2
:=
reflect
.
ValueOf
(
arg
)
k2
,
err
:=
basicKind
(
v2
)
if
err
!=
nil
{
return
false
,
err
}
if
k1
!=
k2
{
return
false
,
errBadComparison
}
truth
:=
false
switch
k1
{
case
boolKind
:
truth
=
v1
.
Bool
()
==
v2
.
Bool
()
case
complexKind
:
truth
=
v1
.
Complex
()
==
v2
.
Complex
()
case
floatKind
:
truth
=
v1
.
Float
()
==
v2
.
Float
()
case
intKind
:
truth
=
v1
.
Int
()
==
v2
.
Int
()
case
stringKind
:
truth
=
v1
.
String
()
==
v2
.
String
()
case
uintKind
:
truth
=
v1
.
Uint
()
==
v2
.
Uint
()
default
:
panic
(
"invalid kind"
)
}
if
truth
{
return
true
,
nil
}
}
return
false
,
nil
}
// ne evaluates the comparison a != b.
func
ne
(
arg1
,
arg2
interface
{})
(
bool
,
error
)
{
// != is the inverse of ==.
equal
,
err
:=
eq
(
arg1
,
arg2
)
return
!
equal
,
err
}
// lt evaluates the comparison a < b.
func
lt
(
arg1
,
arg2
interface
{})
(
bool
,
error
)
{
v1
:=
reflect
.
ValueOf
(
arg1
)
k1
,
err
:=
basicKind
(
v1
)
if
err
!=
nil
{
return
false
,
err
}
v2
:=
reflect
.
ValueOf
(
arg2
)
k2
,
err
:=
basicKind
(
v2
)
if
err
!=
nil
{
return
false
,
err
}
if
k1
!=
k2
{
return
false
,
errBadComparison
}
truth
:=
false
switch
k1
{
case
boolKind
,
complexKind
:
return
false
,
errBadComparisonType
case
floatKind
:
truth
=
v1
.
Float
()
<
v2
.
Float
()
case
intKind
:
truth
=
v1
.
Int
()
<
v2
.
Int
()
case
stringKind
:
truth
=
v1
.
String
()
<
v2
.
String
()
case
uintKind
:
truth
=
v1
.
Uint
()
<
v2
.
Uint
()
default
:
panic
(
"invalid kind"
)
}
return
truth
,
nil
}
// le evaluates the comparison <= b.
func
le
(
arg1
,
arg2
interface
{})
(
bool
,
error
)
{
// <= is < or ==.
lessThan
,
err
:=
lt
(
arg1
,
arg2
)
if
lessThan
||
err
!=
nil
{
return
lessThan
,
err
}
return
eq
(
arg1
,
arg2
)
}
// gt evaluates the comparison a > b.
func
gt
(
arg1
,
arg2
interface
{})
(
bool
,
error
)
{
// > is the inverse of <=.
lessOrEqual
,
err
:=
le
(
arg1
,
arg2
)
if
err
!=
nil
{
return
false
,
err
}
return
!
lessOrEqual
,
nil
}
// ge evaluates the comparison a >= b.
func
ge
(
arg1
,
arg2
interface
{})
(
bool
,
error
)
{
// >= is the inverse of <.
lessThan
,
err
:=
lt
(
arg1
,
arg2
)
if
err
!=
nil
{
return
false
,
err
}
return
!
lessThan
,
nil
}
// go1.2 added template funcs. end
utils
_test.go
→
templatefunc
_test.go
View file @
19119e99
...
...
@@ -7,18 +7,6 @@ import (
"time"
)
func
TestWebTime
(
t
*
testing
.
T
)
{
ts
:=
"Fri, 26 Jul 2013 12:27:42 CST"
l
,
_
:=
time
.
LoadLocation
(
"GST"
)
tt
,
_
:=
time
.
ParseInLocation
(
time
.
RFC1123
,
ts
,
l
)
if
ts
!=
webTime
(
tt
)
{
t
.
Error
(
"should be equal"
)
}
if
"Fri, 26 Jul 2013 12:27:42 GMT"
!=
webTime
(
tt
.
UTC
())
{
t
.
Error
(
"should be equal"
)
}
}
func
TestSubstr
(
t
*
testing
.
T
)
{
s
:=
`012345`
if
Substr
(
s
,
0
,
2
)
!=
"01"
{
...
...
@@ -92,16 +80,6 @@ func TestHtmlunquote(t *testing.T) {
}
}
func
TestInSlice
(
t
*
testing
.
T
)
{
sl
:=
[]
string
{
"A"
,
"b"
}
if
!
inSlice
(
"A"
,
sl
)
{
t
.
Error
(
"should be true"
)
}
if
inSlice
(
"B"
,
sl
)
{
t
.
Error
(
"should be false"
)
}
}
func
TestParseForm
(
t
*
testing
.
T
)
{
type
user
struct
{
Id
int
`form:"-"`
...
...
utils/slice.go
0 → 100644
View file @
19119e99
package
utils
func
InSlice
(
v
string
,
sl
[]
string
)
bool
{
for
_
,
vv
:=
range
sl
{
if
vv
==
v
{
return
true
}
}
return
false
}
utils/slice_test.go
0 → 100644
View file @
19119e99
package
utils
import
(
"testing"
)
func
TestInSlice
(
t
*
testing
.
T
)
{
sl
:=
[]
string
{
"A"
,
"b"
}
if
!
InSlice
(
"A"
,
sl
)
{
t
.
Error
(
"should be true"
)
}
if
InSlice
(
"B"
,
sl
)
{
t
.
Error
(
"should be false"
)
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment