19119e99 by astaxie

move utils to utils libs & func move to templatefunc

1 parent d603a671
...@@ -3,6 +3,7 @@ package beego ...@@ -3,6 +3,7 @@ package beego
3 import ( 3 import (
4 "bytes" 4 "bytes"
5 "crypto/hmac" 5 "crypto/hmac"
6 "crypto/rand"
6 "crypto/sha1" 7 "crypto/sha1"
7 "encoding/base64" 8 "encoding/base64"
8 "errors" 9 "errors"
...@@ -370,7 +371,7 @@ func (c *Controller) XsrfToken() string { ...@@ -370,7 +371,7 @@ func (c *Controller) XsrfToken() string {
370 } else { 371 } else {
371 expire = int64(XSRFExpire) 372 expire = int64(XSRFExpire)
372 } 373 }
373 token = GetRandomString(15) 374 token = getRandomString(15)
374 c.SetSecureCookie(XSRFKEY, "_xsrf", token, expire) 375 c.SetSecureCookie(XSRFKEY, "_xsrf", token, expire)
375 } 376 }
376 c._xsrf_token = token 377 c._xsrf_token = token
...@@ -405,3 +406,14 @@ func (c *Controller) GoToFunc(funcname string) { ...@@ -405,3 +406,14 @@ func (c *Controller) GoToFunc(funcname string) {
405 } 406 }
406 c.gotofunc = funcname 407 c.gotofunc = funcname
407 } 408 }
409
410 //utils func for controller internal
411 func getRandomString(n int) string {
412 const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
413 var bytes = make([]byte, n)
414 rand.Read(bytes)
415 for i, b := range bytes {
416 bytes[i] = alphanum[b%byte(len(alphanum))]
417 }
418 return string(bytes)
419 }
......
...@@ -15,6 +15,7 @@ import ( ...@@ -15,6 +15,7 @@ import (
15 beecontext "github.com/astaxie/beego/context" 15 beecontext "github.com/astaxie/beego/context"
16 "github.com/astaxie/beego/middleware" 16 "github.com/astaxie/beego/middleware"
17 "github.com/astaxie/beego/toolbox" 17 "github.com/astaxie/beego/toolbox"
18 "github.com/astaxie/beego/utils"
18 ) 19 )
19 20
20 const ( 21 const (
...@@ -159,7 +160,7 @@ func (p *ControllerRegistor) Add(pattern string, c ControllerInterface, mappingM ...@@ -159,7 +160,7 @@ func (p *ControllerRegistor) Add(pattern string, c ControllerInterface, mappingM
159 } 160 }
160 comma := strings.Split(colon[0], ",") 161 comma := strings.Split(colon[0], ",")
161 for _, m := range comma { 162 for _, m := range comma {
162 if m == "*" || inSlice(strings.ToLower(m), HTTPMETHOD) { 163 if m == "*" || utils.InSlice(strings.ToLower(m), HTTPMETHOD) {
163 if val := reflectVal.MethodByName(colon[1]); val.IsValid() { 164 if val := reflectVal.MethodByName(colon[1]); val.IsValid() {
164 methods[strings.ToLower(m)] = colon[1] 165 methods[strings.ToLower(m)] = colon[1]
165 } else { 166 } else {
...@@ -272,7 +273,7 @@ func (p *ControllerRegistor) UrlFor(endpoint string, values ...string) string { ...@@ -272,7 +273,7 @@ func (p *ControllerRegistor) UrlFor(endpoint string, values ...string) string {
272 for _, route := range p.fixrouters { 273 for _, route := range p.fixrouters {
273 if route.controllerType.Name() == controllName { 274 if route.controllerType.Name() == controllName {
274 var finded bool 275 var finded bool
275 if inSlice(strings.ToLower(methodName), HTTPMETHOD) { 276 if utils.InSlice(strings.ToLower(methodName), HTTPMETHOD) {
276 if route.hasMethod { 277 if route.hasMethod {
277 if m, ok := route.methods[strings.ToLower(methodName)]; ok && m != methodName { 278 if m, ok := route.methods[strings.ToLower(methodName)]; ok && m != methodName {
278 finded = false 279 finded = false
...@@ -303,7 +304,7 @@ func (p *ControllerRegistor) UrlFor(endpoint string, values ...string) string { ...@@ -303,7 +304,7 @@ func (p *ControllerRegistor) UrlFor(endpoint string, values ...string) string {
303 for _, route := range p.routers { 304 for _, route := range p.routers {
304 if route.controllerType.Name() == controllName { 305 if route.controllerType.Name() == controllName {
305 var finded bool 306 var finded bool
306 if inSlice(strings.ToLower(methodName), HTTPMETHOD) { 307 if utils.InSlice(strings.ToLower(methodName), HTTPMETHOD) {
307 if route.hasMethod { 308 if route.hasMethod {
308 if m, ok := route.methods[strings.ToLower(methodName)]; ok && m != methodName { 309 if m, ok := route.methods[strings.ToLower(methodName)]; ok && m != methodName {
309 finded = false 310 finded = false
...@@ -419,7 +420,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) ...@@ -419,7 +420,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
419 context.Output = beecontext.NewOutput(rw) 420 context.Output = beecontext.NewOutput(rw)
420 } 421 }
421 422
422 if !inSlice(strings.ToLower(r.Method), HTTPMETHOD) { 423 if !utils.InSlice(strings.ToLower(r.Method), HTTPMETHOD) {
423 http.Error(w, "Method Not Allowed", 405) 424 http.Error(w, "Method Not Allowed", 405)
424 goto Admin 425 goto Admin
425 } 426 }
......
...@@ -9,9 +9,10 @@ import ( ...@@ -9,9 +9,10 @@ import (
9 "io/ioutil" 9 "io/ioutil"
10 "os" 10 "os"
11 "path/filepath" 11 "path/filepath"
12 "reflect"
13 "regexp" 12 "regexp"
14 "strings" 13 "strings"
14
15 "github.com/astaxie/beego/utils"
15 ) 16 )
16 17
17 var ( 18 var (
...@@ -144,7 +145,7 @@ func getTplDeep(root, file, parent string, t *template.Template) (*template.Temp ...@@ -144,7 +145,7 @@ func getTplDeep(root, file, parent string, t *template.Template) (*template.Temp
144 } else { 145 } else {
145 fileabspath = filepath.Join(root, file) 146 fileabspath = filepath.Join(root, file)
146 } 147 }
147 if e, _ := FileExists(fileabspath); !e { 148 if e := utils.FileExists(fileabspath); !e {
148 panic("can't find template file" + file) 149 panic("can't find template file" + file)
149 } 150 }
150 data, err := ioutil.ReadFile(fileabspath) 151 data, err := ioutil.ReadFile(fileabspath)
...@@ -238,156 +239,3 @@ func _getTemplate(t0 *template.Template, root string, submods [][]string, others ...@@ -238,156 +239,3 @@ func _getTemplate(t0 *template.Template, root string, submods [][]string, others
238 } 239 }
239 return 240 return
240 } 241 }
241
242 // go1.2 added template funcs. begin
243 var (
244 errBadComparisonType = errors.New("invalid type for comparison")
245 errBadComparison = errors.New("incompatible types for comparison")
246 errNoComparison = errors.New("missing argument for comparison")
247 )
248
249 type kind int
250
251 const (
252 invalidKind kind = iota
253 boolKind
254 complexKind
255 intKind
256 floatKind
257 integerKind
258 stringKind
259 uintKind
260 )
261
262 func basicKind(v reflect.Value) (kind, error) {
263 switch v.Kind() {
264 case reflect.Bool:
265 return boolKind, nil
266 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
267 return intKind, nil
268 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
269 return uintKind, nil
270 case reflect.Float32, reflect.Float64:
271 return floatKind, nil
272 case reflect.Complex64, reflect.Complex128:
273 return complexKind, nil
274 case reflect.String:
275 return stringKind, nil
276 }
277 return invalidKind, errBadComparisonType
278 }
279
280 // eq evaluates the comparison a == b || a == c || ...
281 func eq(arg1 interface{}, arg2 ...interface{}) (bool, error) {
282 v1 := reflect.ValueOf(arg1)
283 k1, err := basicKind(v1)
284 if err != nil {
285 return false, err
286 }
287 if len(arg2) == 0 {
288 return false, errNoComparison
289 }
290 for _, arg := range arg2 {
291 v2 := reflect.ValueOf(arg)
292 k2, err := basicKind(v2)
293 if err != nil {
294 return false, err
295 }
296 if k1 != k2 {
297 return false, errBadComparison
298 }
299 truth := false
300 switch k1 {
301 case boolKind:
302 truth = v1.Bool() == v2.Bool()
303 case complexKind:
304 truth = v1.Complex() == v2.Complex()
305 case floatKind:
306 truth = v1.Float() == v2.Float()
307 case intKind:
308 truth = v1.Int() == v2.Int()
309 case stringKind:
310 truth = v1.String() == v2.String()
311 case uintKind:
312 truth = v1.Uint() == v2.Uint()
313 default:
314 panic("invalid kind")
315 }
316 if truth {
317 return true, nil
318 }
319 }
320 return false, nil
321 }
322
323 // ne evaluates the comparison a != b.
324 func ne(arg1, arg2 interface{}) (bool, error) {
325 // != is the inverse of ==.
326 equal, err := eq(arg1, arg2)
327 return !equal, err
328 }
329
330 // lt evaluates the comparison a < b.
331 func lt(arg1, arg2 interface{}) (bool, error) {
332 v1 := reflect.ValueOf(arg1)
333 k1, err := basicKind(v1)
334 if err != nil {
335 return false, err
336 }
337 v2 := reflect.ValueOf(arg2)
338 k2, err := basicKind(v2)
339 if err != nil {
340 return false, err
341 }
342 if k1 != k2 {
343 return false, errBadComparison
344 }
345 truth := false
346 switch k1 {
347 case boolKind, complexKind:
348 return false, errBadComparisonType
349 case floatKind:
350 truth = v1.Float() < v2.Float()
351 case intKind:
352 truth = v1.Int() < v2.Int()
353 case stringKind:
354 truth = v1.String() < v2.String()
355 case uintKind:
356 truth = v1.Uint() < v2.Uint()
357 default:
358 panic("invalid kind")
359 }
360 return truth, nil
361 }
362
363 // le evaluates the comparison <= b.
364 func le(arg1, arg2 interface{}) (bool, error) {
365 // <= is < or ==.
366 lessThan, err := lt(arg1, arg2)
367 if lessThan || err != nil {
368 return lessThan, err
369 }
370 return eq(arg1, arg2)
371 }
372
373 // gt evaluates the comparison a > b.
374 func gt(arg1, arg2 interface{}) (bool, error) {
375 // > is the inverse of <=.
376 lessOrEqual, err := le(arg1, arg2)
377 if err != nil {
378 return false, err
379 }
380 return !lessOrEqual, nil
381 }
382
383 // ge evaluates the comparison a >= b.
384 func ge(arg1, arg2 interface{}) (bool, error) {
385 // >= is the inverse of <.
386 lessThan, err := lt(arg1, arg2)
387 if err != nil {
388 return false, err
389 }
390 return !lessThan, nil
391 }
392
393 // go1.2 added template funcs. end
......
1 package beego 1 package beego
2 2
3 import ( 3 import (
4 "crypto/rand" 4 "errors"
5 "fmt" 5 "fmt"
6 "html/template" 6 "html/template"
7 "net/url" 7 "net/url"
8 "os" 8 "reflect"
9 "reflect" 9 "regexp"
10 "regexp" 10 "strconv"
11 "strconv" 11 "strings"
12 "strings" 12 "time"
13 "time" 13 )
14 ) 14
15 15 // Substr() return the substr from start to length
16 func webTime(t time.Time) string { 16 func Substr(s string, start, length int) string {
17 ftime := t.Format(time.RFC1123) 17 bt := []rune(s)
18 if strings.HasSuffix(ftime, "UTC") { 18 if start < 0 {
19 ftime = ftime[0:len(ftime)-3] + "GMT" 19 start = 0
20 } 20 }
21 return ftime 21 var end int
22 } 22 if (start + length) > (len(bt) - 1) {
23 23 end = len(bt)
24 func Substr(s string, start, length int) string { 24 } else {
25 bt := []rune(s) 25 end = start + length
26 if start < 0 { 26 }
27 start = 0 27 return string(bt[start:end])
28 } 28 }
29 var end int 29
30 if (start + length) > (len(bt) - 1) { 30 // Html2str() returns escaping text convert from html
31 end = len(bt) 31 func Html2str(html string) string {
32 } else { 32 src := string(html)
33 end = start + length 33
34 } 34 //将HTML标签全转换成小写
35 return string(bt[start:end]) 35 re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")
36 } 36 src = re.ReplaceAllStringFunc(src, strings.ToLower)
37 37
38 // Html2str() returns escaping text convert from html 38 //去除STYLE
39 func Html2str(html string) string { 39 re, _ = regexp.Compile("\\<style[\\S\\s]+?\\</style\\>")
40 src := string(html) 40 src = re.ReplaceAllString(src, "")
41 41
42 //将HTML标签全转换成小写 42 //去除SCRIPT
43 re, _ := regexp.Compile("\\<[\\S\\s]+?\\>") 43 re, _ = regexp.Compile("\\<script[\\S\\s]+?\\</script\\>")
44 src = re.ReplaceAllStringFunc(src, strings.ToLower) 44 src = re.ReplaceAllString(src, "")
45 45
46 //去除STYLE 46 //去除所有尖括号内的HTML代码,并换成换行符
47 re, _ = regexp.Compile("\\<style[\\S\\s]+?\\</style\\>") 47 re, _ = regexp.Compile("\\<[\\S\\s]+?\\>")
48 src = re.ReplaceAllString(src, "") 48 src = re.ReplaceAllString(src, "\n")
49 49
50 //去除SCRIPT 50 //去除连续的换行符
51 re, _ = regexp.Compile("\\<script[\\S\\s]+?\\</script\\>") 51 re, _ = regexp.Compile("\\s{2,}")
52 src = re.ReplaceAllString(src, "") 52 src = re.ReplaceAllString(src, "\n")
53 53
54 //去除所有尖括号内的HTML代码,并换成换行符 54 return strings.TrimSpace(src)
55 re, _ = regexp.Compile("\\<[\\S\\s]+?\\>") 55 }
56 src = re.ReplaceAllString(src, "\n") 56
57 57 // DateFormat takes a time and a layout string and returns a string with the formatted date. Used by the template parser as "dateformat"
58 //去除连续的换行符 58 func DateFormat(t time.Time, layout string) (datestring string) {
59 re, _ = regexp.Compile("\\s{2,}") 59 datestring = t.Format(layout)
60 src = re.ReplaceAllString(src, "\n") 60 return
61 61 }
62 return strings.TrimSpace(src) 62
63 } 63 var DatePatterns = []string{
64 64 // year
65 // DateFormat takes a time and a layout string and returns a string with the formatted date. Used by the template parser as "dateformat" 65 "Y", "2006", // A full numeric representation of a year, 4 digits Examples: 1999 or 2003
66 func DateFormat(t time.Time, layout string) (datestring string) { 66 "y", "06", //A two digit representation of a year Examples: 99 or 03
67 datestring = t.Format(layout) 67
68 return 68 // month
69 } 69 "m", "01", // Numeric representation of a month, with leading zeros 01 through 12
70 70 "n", "1", // Numeric representation of a month, without leading zeros 1 through 12
71 var DatePatterns = []string{ 71 "M", "Jan", // A short textual representation of a month, three letters Jan through Dec
72 // year 72 "F", "January", // A full textual representation of a month, such as January or March January through December
73 "Y", "2006", // A full numeric representation of a year, 4 digits Examples: 1999 or 2003 73
74 "y", "06", //A two digit representation of a year Examples: 99 or 03 74 // day
75 75 "d", "02", // Day of the month, 2 digits with leading zeros 01 to 31
76 // month 76 "j", "2", // Day of the month without leading zeros 1 to 31
77 "m", "01", // Numeric representation of a month, with leading zeros 01 through 12 77
78 "n", "1", // Numeric representation of a month, without leading zeros 1 through 12 78 // week
79 "M", "Jan", // A short textual representation of a month, three letters Jan through Dec 79 "D", "Mon", // A textual representation of a day, three letters Mon through Sun
80 "F", "January", // A full textual representation of a month, such as January or March January through December 80 "l", "Monday", // A full textual representation of the day of the week Sunday through Saturday
81 81
82 // day 82 // time
83 "d", "02", // Day of the month, 2 digits with leading zeros 01 to 31 83 "g", "3", // 12-hour format of an hour without leading zeros 1 through 12
84 "j", "2", // Day of the month without leading zeros 1 to 31 84 "G", "15", // 24-hour format of an hour without leading zeros 0 through 23
85 85 "h", "03", // 12-hour format of an hour with leading zeros 01 through 12
86 // week 86 "H", "15", // 24-hour format of an hour with leading zeros 00 through 23
87 "D", "Mon", // A textual representation of a day, three letters Mon through Sun 87
88 "l", "Monday", // A full textual representation of the day of the week Sunday through Saturday 88 "a", "pm", // Lowercase Ante meridiem and Post meridiem am or pm
89 89 "A", "PM", // Uppercase Ante meridiem and Post meridiem AM or PM
90 // time 90
91 "g", "3", // 12-hour format of an hour without leading zeros 1 through 12 91 "i", "04", // Minutes with leading zeros 00 to 59
92 "G", "15", // 24-hour format of an hour without leading zeros 0 through 23 92 "s", "05", // Seconds, with leading zeros 00 through 59
93 "h", "03", // 12-hour format of an hour with leading zeros 01 through 12 93
94 "H", "15", // 24-hour format of an hour with leading zeros 00 through 23 94 // time zone
95 95 "T", "MST",
96 "a", "pm", // Lowercase Ante meridiem and Post meridiem am or pm 96 "P", "-07:00",
97 "A", "PM", // Uppercase Ante meridiem and Post meridiem AM or PM 97 "O", "-0700",
98 98
99 "i", "04", // Minutes with leading zeros 00 to 59 99 // RFC 2822
100 "s", "05", // Seconds, with leading zeros 00 through 59 100 "r", time.RFC1123Z,
101 101 }
102 // time zone 102
103 "T", "MST", 103 // Parse Date use PHP time format
104 "P", "-07:00", 104 func DateParse(dateString, format string) (time.Time, error) {
105 "O", "-0700", 105 replacer := strings.NewReplacer(DatePatterns...)
106 106 format = replacer.Replace(format)
107 // RFC 2822 107 return time.ParseInLocation(format, dateString, time.Local)
108 "r", time.RFC1123Z, 108 }
109 } 109
110 110 // Date takes a PHP like date func to Go's time format
111 // Parse Date use PHP time format 111 func Date(t time.Time, format string) string {
112 func DateParse(dateString, format string) (time.Time, error) { 112 replacer := strings.NewReplacer(DatePatterns...)
113 replacer := strings.NewReplacer(DatePatterns...) 113 format = replacer.Replace(format)
114 format = replacer.Replace(format) 114 return t.Format(format)
115 return time.ParseInLocation(format, dateString, time.Local) 115 }
116 } 116
117 117 // 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.
118 // Date takes a PHP like date func to Go's time format 118 // Whitespace is trimmed. Used by the template parser as "eq"
119 func Date(t time.Time, format string) string { 119 func Compare(a, b interface{}) (equal bool) {
120 replacer := strings.NewReplacer(DatePatterns...) 120 equal = false
121 format = replacer.Replace(format) 121 if strings.TrimSpace(fmt.Sprintf("%v", a)) == strings.TrimSpace(fmt.Sprintf("%v", b)) {
122 return t.Format(format) 122 equal = true
123 } 123 }
124 124 return
125 // 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. 125 }
126 // Whitespace is trimmed. Used by the template parser as "eq" 126
127 func Compare(a, b interface{}) (equal bool) { 127 func Str2html(raw string) template.HTML {
128 equal = false 128 return template.HTML(raw)
129 if strings.TrimSpace(fmt.Sprintf("%v", a)) == strings.TrimSpace(fmt.Sprintf("%v", b)) { 129 }
130 equal = true 130
131 } 131 func Htmlquote(src string) string {
132 return 132 //HTML编码为实体符号
133 } 133 /*
134 134 Encodes `text` for raw use in HTML.
135 func Str2html(raw string) template.HTML { 135 >>> htmlquote("<'&\\">")
136 return template.HTML(raw) 136 '&lt;&#39;&amp;&quot;&gt;'
137 } 137 */
138 138
139 func Htmlquote(src string) string { 139 text := string(src)
140 //HTML编码为实体符号 140
141 /* 141 text = strings.Replace(text, "&", "&amp;", -1) // Must be done first!
142 Encodes `text` for raw use in HTML. 142 text = strings.Replace(text, "<", "&lt;", -1)
143 >>> htmlquote("<'&\\">") 143 text = strings.Replace(text, ">", "&gt;", -1)
144 '&lt;&#39;&amp;&quot;&gt;' 144 text = strings.Replace(text, "'", "&#39;", -1)
145 */ 145 text = strings.Replace(text, "\"", "&quot;", -1)
146 146 text = strings.Replace(text, "“", "&ldquo;", -1)
147 text := string(src) 147 text = strings.Replace(text, "”", "&rdquo;", -1)
148 148 text = strings.Replace(text, " ", "&nbsp;", -1)
149 text = strings.Replace(text, "&", "&amp;", -1) // Must be done first! 149
150 text = strings.Replace(text, "<", "&lt;", -1) 150 return strings.TrimSpace(text)
151 text = strings.Replace(text, ">", "&gt;", -1) 151 }
152 text = strings.Replace(text, "'", "&#39;", -1) 152
153 text = strings.Replace(text, "\"", "&quot;", -1) 153 func Htmlunquote(src string) string {
154 text = strings.Replace(text, "“", "&ldquo;", -1) 154 //实体符号解释为HTML
155 text = strings.Replace(text, "”", "&rdquo;", -1) 155 /*
156 text = strings.Replace(text, " ", "&nbsp;", -1) 156 Decodes `text` that's HTML quoted.
157 157 >>> htmlunquote('&lt;&#39;&amp;&quot;&gt;')
158 return strings.TrimSpace(text) 158 '<\\'&">'
159 } 159 */
160 160
161 func Htmlunquote(src string) string { 161 // strings.Replace(s, old, new, n)
162 //实体符号解释为HTML 162 // 在s字符串中,把old字符串替换为new字符串,n表示替换的次数,小于0表示全部替换
163 /* 163
164 Decodes `text` that's HTML quoted. 164 text := string(src)
165 >>> htmlunquote('&lt;&#39;&amp;&quot;&gt;') 165 text = strings.Replace(text, "&nbsp;", " ", -1)
166 '<\\'&">' 166 text = strings.Replace(text, "&rdquo;", "”", -1)
167 */ 167 text = strings.Replace(text, "&ldquo;", "“", -1)
168 168 text = strings.Replace(text, "&quot;", "\"", -1)
169 // strings.Replace(s, old, new, n) 169 text = strings.Replace(text, "&#39;", "'", -1)
170 // 在s字符串中,把old字符串替换为new字符串,n表示替换的次数,小于0表示全部替换 170 text = strings.Replace(text, "&gt;", ">", -1)
171 171 text = strings.Replace(text, "&lt;", "<", -1)
172 text := string(src) 172 text = strings.Replace(text, "&amp;", "&", -1) // Must be done last!
173 text = strings.Replace(text, "&nbsp;", " ", -1) 173
174 text = strings.Replace(text, "&rdquo;", "”", -1) 174 return strings.TrimSpace(text)
175 text = strings.Replace(text, "&ldquo;", "“", -1) 175 }
176 text = strings.Replace(text, "&quot;", "\"", -1) 176
177 text = strings.Replace(text, "&#39;", "'", -1) 177 // This will reference the index function local to the current blueprint:
178 text = strings.Replace(text, "&gt;", ">", -1) 178 // UrlFor(".index")
179 text = strings.Replace(text, "&lt;", "<", -1) 179 // ... print UrlFor("index")
180 text = strings.Replace(text, "&amp;", "&", -1) // Must be done last! 180 // ... print UrlFor("login")
181 181 // ... print UrlFor("login", "next","/"")
182 return strings.TrimSpace(text) 182 // ... print UrlFor("profile", "username","John Doe")
183 } 183 // ...
184 184 // /
185 func inSlice(v string, sl []string) bool { 185 // /login
186 for _, vv := range sl { 186 // /login?next=/
187 if vv == v { 187 // /user/John%20Doe
188 return true 188 func UrlFor(endpoint string, values ...string) string {
189 } 189 return BeeApp.UrlFor(endpoint, values...)
190 } 190 }
191 return false 191
192 } 192 //This can be changed to a better name
193 193 func AssetsJs(src string) template.HTML {
194 // parse form values to struct via tag 194 text := string(src)
195 func ParseForm(form url.Values, obj interface{}) error { 195
196 objT := reflect.TypeOf(obj) 196 text = "<script src=\"" + src + "\"></script>"
197 objV := reflect.ValueOf(obj) 197
198 if !isStructPtr(objT) { 198 return template.HTML(text)
199 return fmt.Errorf("%v must be a struct pointer", obj) 199 }
200 } 200
201 objT = objT.Elem() 201 //This can be changed to a better name
202 objV = objV.Elem() 202 func AssetsCss(src string) template.HTML {
203 203 text := string(src)
204 for i := 0; i < objT.NumField(); i++ { 204
205 fieldV := objV.Field(i) 205 text = "<link href=\"" + src + "\" rel=\"stylesheet\" />"
206 if !fieldV.CanSet() { 206
207 continue 207 return template.HTML(text)
208 } 208 }
209 209
210 fieldT := objT.Field(i) 210 // parse form values to struct via tag
211 tags := strings.Split(fieldT.Tag.Get("form"), ",") 211 func ParseForm(form url.Values, obj interface{}) error {
212 var tag string 212 objT := reflect.TypeOf(obj)
213 if len(tags) == 0 || len(tags[0]) == 0 { 213 objV := reflect.ValueOf(obj)
214 tag = fieldT.Name 214 if !isStructPtr(objT) {
215 } else if tags[0] == "-" { 215 return fmt.Errorf("%v must be a struct pointer", obj)
216 continue 216 }
217 } else { 217 objT = objT.Elem()
218 tag = tags[0] 218 objV = objV.Elem()
219 } 219
220 220 for i := 0; i < objT.NumField(); i++ {
221 value := form.Get(tag) 221 fieldV := objV.Field(i)
222 if len(value) == 0 { 222 if !fieldV.CanSet() {
223 continue 223 continue
224 } 224 }
225 225
226 switch fieldT.Type.Kind() { 226 fieldT := objT.Field(i)
227 case reflect.Bool: 227 tags := strings.Split(fieldT.Tag.Get("form"), ",")
228 b, err := strconv.ParseBool(value) 228 var tag string
229 if err != nil { 229 if len(tags) == 0 || len(tags[0]) == 0 {
230 return err 230 tag = fieldT.Name
231 } 231 } else if tags[0] == "-" {
232 fieldV.SetBool(b) 232 continue
233 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 233 } else {
234 x, err := strconv.ParseInt(value, 10, 64) 234 tag = tags[0]
235 if err != nil { 235 }
236 return err 236
237 } 237 value := form.Get(tag)
238 fieldV.SetInt(x) 238 if len(value) == 0 {
239 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 239 continue
240 x, err := strconv.ParseUint(value, 10, 64) 240 }
241 if err != nil { 241
242 return err 242 switch fieldT.Type.Kind() {
243 } 243 case reflect.Bool:
244 fieldV.SetUint(x) 244 b, err := strconv.ParseBool(value)
245 case reflect.Float32, reflect.Float64: 245 if err != nil {
246 x, err := strconv.ParseFloat(value, 64) 246 return err
247 if err != nil { 247 }
248 return err 248 fieldV.SetBool(b)
249 } 249 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
250 fieldV.SetFloat(x) 250 x, err := strconv.ParseInt(value, 10, 64)
251 case reflect.Interface: 251 if err != nil {
252 fieldV.Set(reflect.ValueOf(value)) 252 return err
253 case reflect.String: 253 }
254 fieldV.SetString(value) 254 fieldV.SetInt(x)
255 } 255 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
256 } 256 x, err := strconv.ParseUint(value, 10, 64)
257 return nil 257 if err != nil {
258 } 258 return err
259 259 }
260 // form types for RenderForm function 260 fieldV.SetUint(x)
261 var FormType = map[string]bool{ 261 case reflect.Float32, reflect.Float64:
262 "text": true, 262 x, err := strconv.ParseFloat(value, 64)
263 "textarea": true, 263 if err != nil {
264 "hidden": true, 264 return err
265 "password": true, 265 }
266 } 266 fieldV.SetFloat(x)
267 267 case reflect.Interface:
268 var unKind = map[reflect.Kind]bool{ 268 fieldV.Set(reflect.ValueOf(value))
269 reflect.Uintptr: true, 269 case reflect.String:
270 reflect.Complex64: true, 270 fieldV.SetString(value)
271 reflect.Complex128: true, 271 }
272 reflect.Array: true, 272 }
273 reflect.Chan: true, 273 return nil
274 reflect.Func: true, 274 }
275 reflect.Map: true, 275
276 reflect.Ptr: true, 276 // form types for RenderForm function
277 reflect.Slice: true, 277 var FormType = map[string]bool{
278 reflect.Struct: true, 278 "text": true,
279 reflect.UnsafePointer: true, 279 "textarea": true,
280 } 280 "hidden": true,
281 281 "password": true,
282 // obj must be a struct pointer 282 }
283 func RenderForm(obj interface{}) template.HTML { 283
284 objT := reflect.TypeOf(obj) 284 var unKind = map[reflect.Kind]bool{
285 objV := reflect.ValueOf(obj) 285 reflect.Uintptr: true,
286 if !isStructPtr(objT) { 286 reflect.Complex64: true,
287 return template.HTML("") 287 reflect.Complex128: true,
288 } 288 reflect.Array: true,
289 objT = objT.Elem() 289 reflect.Chan: true,
290 objV = objV.Elem() 290 reflect.Func: true,
291 291 reflect.Map: true,
292 var raw []string 292 reflect.Ptr: true,
293 for i := 0; i < objT.NumField(); i++ { 293 reflect.Slice: true,
294 fieldV := objV.Field(i) 294 reflect.Struct: true,
295 if !fieldV.CanSet() || unKind[fieldV.Kind()] { 295 reflect.UnsafePointer: true,
296 continue 296 }
297 } 297
298 298 // obj must be a struct pointer
299 fieldT := objT.Field(i) 299 func RenderForm(obj interface{}) template.HTML {
300 tags := strings.Split(fieldT.Tag.Get("form"), ",") 300 objT := reflect.TypeOf(obj)
301 label := fieldT.Name + ": " 301 objV := reflect.ValueOf(obj)
302 name := fieldT.Name 302 if !isStructPtr(objT) {
303 fType := "text" 303 return template.HTML("")
304 304 }
305 switch len(tags) { 305 objT = objT.Elem()
306 case 1: 306 objV = objV.Elem()
307 if tags[0] == "-" { 307
308 continue 308 var raw []string
309 } 309 for i := 0; i < objT.NumField(); i++ {
310 if len(tags[0]) > 0 { 310 fieldV := objV.Field(i)
311 name = tags[0] 311 if !fieldV.CanSet() || unKind[fieldV.Kind()] {
312 } 312 continue
313 case 2: 313 }
314 if len(tags[0]) > 0 { 314
315 name = tags[0] 315 fieldT := objT.Field(i)
316 } 316 tags := strings.Split(fieldT.Tag.Get("form"), ",")
317 if len(tags[1]) > 0 { 317 label := fieldT.Name + ": "
318 fType = tags[1] 318 name := fieldT.Name
319 } 319 fType := "text"
320 case 3: 320
321 if len(tags[0]) > 0 { 321 switch len(tags) {
322 name = tags[0] 322 case 1:
323 } 323 if tags[0] == "-" {
324 if len(tags[1]) > 0 { 324 continue
325 fType = tags[1] 325 }
326 } 326 if len(tags[0]) > 0 {
327 if len(tags[2]) > 0 { 327 name = tags[0]
328 label = tags[2] 328 }
329 } 329 case 2:
330 } 330 if len(tags[0]) > 0 {
331 331 name = tags[0]
332 raw = append(raw, fmt.Sprintf(`%v<input name="%v" type="%v" value="%v">`, 332 }
333 label, name, fType, fieldV.Interface())) 333 if len(tags[1]) > 0 {
334 } 334 fType = tags[1]
335 return template.HTML(strings.Join(raw, "</br>")) 335 }
336 } 336 case 3:
337 337 if len(tags[0]) > 0 {
338 func isStructPtr(t reflect.Type) bool { 338 name = tags[0]
339 return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct 339 }
340 } 340 if len(tags[1]) > 0 {
341 341 fType = tags[1]
342 func stringsToJson(str string) string { 342 }
343 rs := []rune(str) 343 if len(tags[2]) > 0 {
344 jsons := "" 344 label = tags[2]
345 for _, r := range rs { 345 }
346 rint := int(r) 346 }
347 if rint < 128 { 347
348 jsons += string(r) 348 raw = append(raw, fmt.Sprintf(`%v<input name="%v" type="%v" value="%v">`,
349 } else { 349 label, name, fType, fieldV.Interface()))
350 jsons += "\\u" + strconv.FormatInt(int64(rint), 16) // json 350 }
351 } 351 return template.HTML(strings.Join(raw, "</br>"))
352 } 352 }
353 return jsons 353
354 } 354 func isStructPtr(t reflect.Type) bool {
355 355 return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct
356 func FileExists(path string) (bool, error) { 356 }
357 _, err := os.Stat(path) 357
358 if err == nil { 358 // go1.2 added template funcs. begin
359 return true, nil 359 var (
360 } 360 errBadComparisonType = errors.New("invalid type for comparison")
361 if os.IsNotExist(err) { 361 errBadComparison = errors.New("incompatible types for comparison")
362 return false, nil 362 errNoComparison = errors.New("missing argument for comparison")
363 } 363 )
364 return false, err 364
365 } 365 type kind int
366 366
367 func GetRandomString(n int) string { 367 const (
368 const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 368 invalidKind kind = iota
369 var bytes = make([]byte, n) 369 boolKind
370 rand.Read(bytes) 370 complexKind
371 for i, b := range bytes { 371 intKind
372 bytes[i] = alphanum[b%byte(len(alphanum))] 372 floatKind
373 } 373 integerKind
374 return string(bytes) 374 stringKind
375 } 375 uintKind
376 376 )
377 // This will reference the index function local to the current blueprint: 377
378 // UrlFor(".index") 378 func basicKind(v reflect.Value) (kind, error) {
379 // ... print UrlFor("index") 379 switch v.Kind() {
380 // ... print UrlFor("login") 380 case reflect.Bool:
381 // ... print UrlFor("login", "next","/"") 381 return boolKind, nil
382 // ... print UrlFor("profile", "username","John Doe") 382 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
383 // ... 383 return intKind, nil
384 // / 384 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
385 // /login 385 return uintKind, nil
386 // /login?next=/ 386 case reflect.Float32, reflect.Float64:
387 // /user/John%20Doe 387 return floatKind, nil
388 func UrlFor(endpoint string, values ...string) string { 388 case reflect.Complex64, reflect.Complex128:
389 return BeeApp.UrlFor(endpoint, values...) 389 return complexKind, nil
390 } 390 case reflect.String:
391 391 return stringKind, nil
392 392 }
393 //This can be changed to a better name 393 return invalidKind, errBadComparisonType
394 func AssetsJs(src string) template.HTML { 394 }
395 text := string(src) 395
396 396 // eq evaluates the comparison a == b || a == c || ...
397 text = "<script src=\""+src+"\"></script>" 397 func eq(arg1 interface{}, arg2 ...interface{}) (bool, error) {
398 398 v1 := reflect.ValueOf(arg1)
399 return template.HTML(text) 399 k1, err := basicKind(v1)
400 } 400 if err != nil {
401 401 return false, err
402 //This can be changed to a better name 402 }
403 func AssetsCss(src string) template.HTML { 403 if len(arg2) == 0 {
404 text := string(src) 404 return false, errNoComparison
405 405 }
406 text = "<link href=\""+src+"\" rel=\"stylesheet\" />" 406 for _, arg := range arg2 {
407 407 v2 := reflect.ValueOf(arg)
408 return template.HTML(text) 408 k2, err := basicKind(v2)
409 } 409 if err != nil {
410 return false, err
411 }
412 if k1 != k2 {
413 return false, errBadComparison
414 }
415 truth := false
416 switch k1 {
417 case boolKind:
418 truth = v1.Bool() == v2.Bool()
419 case complexKind:
420 truth = v1.Complex() == v2.Complex()
421 case floatKind:
422 truth = v1.Float() == v2.Float()
423 case intKind:
424 truth = v1.Int() == v2.Int()
425 case stringKind:
426 truth = v1.String() == v2.String()
427 case uintKind:
428 truth = v1.Uint() == v2.Uint()
429 default:
430 panic("invalid kind")
431 }
432 if truth {
433 return true, nil
434 }
435 }
436 return false, nil
437 }
438
439 // ne evaluates the comparison a != b.
440 func ne(arg1, arg2 interface{}) (bool, error) {
441 // != is the inverse of ==.
442 equal, err := eq(arg1, arg2)
443 return !equal, err
444 }
445
446 // lt evaluates the comparison a < b.
447 func lt(arg1, arg2 interface{}) (bool, error) {
448 v1 := reflect.ValueOf(arg1)
449 k1, err := basicKind(v1)
450 if err != nil {
451 return false, err
452 }
453 v2 := reflect.ValueOf(arg2)
454 k2, err := basicKind(v2)
455 if err != nil {
456 return false, err
457 }
458 if k1 != k2 {
459 return false, errBadComparison
460 }
461 truth := false
462 switch k1 {
463 case boolKind, complexKind:
464 return false, errBadComparisonType
465 case floatKind:
466 truth = v1.Float() < v2.Float()
467 case intKind:
468 truth = v1.Int() < v2.Int()
469 case stringKind:
470 truth = v1.String() < v2.String()
471 case uintKind:
472 truth = v1.Uint() < v2.Uint()
473 default:
474 panic("invalid kind")
475 }
476 return truth, nil
477 }
478
479 // le evaluates the comparison <= b.
480 func le(arg1, arg2 interface{}) (bool, error) {
481 // <= is < or ==.
482 lessThan, err := lt(arg1, arg2)
483 if lessThan || err != nil {
484 return lessThan, err
485 }
486 return eq(arg1, arg2)
487 }
488
489 // gt evaluates the comparison a > b.
490 func gt(arg1, arg2 interface{}) (bool, error) {
491 // > is the inverse of <=.
492 lessOrEqual, err := le(arg1, arg2)
493 if err != nil {
494 return false, err
495 }
496 return !lessOrEqual, nil
497 }
498
499 // ge evaluates the comparison a >= b.
500 func ge(arg1, arg2 interface{}) (bool, error) {
501 // >= is the inverse of <.
502 lessThan, err := lt(arg1, arg2)
503 if err != nil {
504 return false, err
505 }
506 return !lessThan, nil
507 }
508
509 // go1.2 added template funcs. end
......
...@@ -7,18 +7,6 @@ import ( ...@@ -7,18 +7,6 @@ import (
7 "time" 7 "time"
8 ) 8 )
9 9
10 func TestWebTime(t *testing.T) {
11 ts := "Fri, 26 Jul 2013 12:27:42 CST"
12 l, _ := time.LoadLocation("GST")
13 tt, _ := time.ParseInLocation(time.RFC1123, ts, l)
14 if ts != webTime(tt) {
15 t.Error("should be equal")
16 }
17 if "Fri, 26 Jul 2013 12:27:42 GMT" != webTime(tt.UTC()) {
18 t.Error("should be equal")
19 }
20 }
21
22 func TestSubstr(t *testing.T) { 10 func TestSubstr(t *testing.T) {
23 s := `012345` 11 s := `012345`
24 if Substr(s, 0, 2) != "01" { 12 if Substr(s, 0, 2) != "01" {
...@@ -92,16 +80,6 @@ func TestHtmlunquote(t *testing.T) { ...@@ -92,16 +80,6 @@ func TestHtmlunquote(t *testing.T) {
92 } 80 }
93 } 81 }
94 82
95 func TestInSlice(t *testing.T) {
96 sl := []string{"A", "b"}
97 if !inSlice("A", sl) {
98 t.Error("should be true")
99 }
100 if inSlice("B", sl) {
101 t.Error("should be false")
102 }
103 }
104
105 func TestParseForm(t *testing.T) { 83 func TestParseForm(t *testing.T) {
106 type user struct { 84 type user struct {
107 Id int `form:"-"` 85 Id int `form:"-"`
......
1 package utils
2
3 func InSlice(v string, sl []string) bool {
4 for _, vv := range sl {
5 if vv == v {
6 return true
7 }
8 }
9 return false
10 }
1 package utils
2
3 import (
4 "testing"
5 )
6
7 func TestInSlice(t *testing.T) {
8 sl := []string{"A", "b"}
9 if !InSlice("A", sl) {
10 t.Error("should be true")
11 }
12 if InSlice("B", sl) {
13 t.Error("should be false")
14 }
15 }
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!