diff --git a/controller.go b/controller.go
index 78e6c34f..261de3df 100644
--- a/controller.go
+++ b/controller.go
@@ -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 = GetRandomString(15)
+ token = getRandomString(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)
+}
diff --git a/router.go b/router.go
index 0cd668a0..c36db4fb 100644
--- a/router.go
+++ b/router.go
@@ -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 == "*" || inSlice(strings.ToLower(m), HTTPMETHOD) {
+ if m == "*" || utils.InSlice(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 inSlice(strings.ToLower(methodName), HTTPMETHOD) {
+ if utils.InSlice(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 inSlice(strings.ToLower(methodName), HTTPMETHOD) {
+ if utils.InSlice(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 !inSlice(strings.ToLower(r.Method), HTTPMETHOD) {
+ if !utils.InSlice(strings.ToLower(r.Method), HTTPMETHOD) {
http.Error(w, "Method Not Allowed", 405)
goto Admin
}
diff --git a/template.go b/template.go
index 5c56da74..31d34a75 100644
--- a/template.go
+++ b/template.go
@@ -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
diff --git a/utils.go b/templatefunc.go
similarity index 72%
rename from utils.go
rename to templatefunc.go
index fafe4190..88acbb3f 100644
--- a/utils.go
+++ b/templatefunc.go
@@ -1,409 +1,509 @@
-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("\\")
+ src = re.ReplaceAllString(src, "")
+
+ //去除SCRIPT
+ re, _ = regexp.Compile("\\"
+
+ return template.HTML(text)
+}
+
+//This can be changed to a better name
+func AssetsCss(src string) template.HTML {
+ text := string(src)
+
+ text = ""
+
+ 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`,
+ label, name, fType, fieldV.Interface()))
+ }
+ return template.HTML(strings.Join(raw, ""))
+}
+
+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
diff --git a/utils_test.go b/templatefunc_test.go
similarity index 88%
rename from utils_test.go
rename to templatefunc_test.go
index b6a5bc58..726ce2d2 100644
--- a/utils_test.go
+++ b/templatefunc_test.go
@@ -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:"-"`
diff --git a/utils/slice.go b/utils/slice.go
new file mode 100644
index 00000000..fe6555f1
--- /dev/null
+++ b/utils/slice.go
@@ -0,0 +1,10 @@
+package utils
+
+func InSlice(v string, sl []string) bool {
+ for _, vv := range sl {
+ if vv == v {
+ return true
+ }
+ }
+ return false
+}
diff --git a/utils/slice_test.go b/utils/slice_test.go
new file mode 100644
index 00000000..d06a94a6
--- /dev/null
+++ b/utils/slice_test.go
@@ -0,0 +1,15 @@
+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")
+ }
+}