1//This package is copied from Go library text/template.
2//The original private functions eq, ge, gt, le, lt, and ne
3//are exported as public functions.
4package template
5
6import (
7	"bytes"
8	"errors"
9	"fmt"
10	"io"
11	"net/url"
12	"reflect"
13	"strings"
14	"unicode"
15	"unicode/utf8"
16)
17
18var Equal = eq
19var GreaterEqual = ge
20var Greater = gt
21var LessEqual = le
22var Less = lt
23var NotEqual = ne
24
25// FuncMap is the type of the map defining the mapping from names to functions.
26// Each function must have either a single return value, or two return values of
27// which the second has type error. In that case, if the second (error)
28// return value evaluates to non-nil during execution, execution terminates and
29// Execute returns that error.
30type FuncMap map[string]interface{}
31
32var builtins = FuncMap{
33	"and":      and,
34	"call":     call,
35	"html":     HTMLEscaper,
36	"index":    index,
37	"js":       JSEscaper,
38	"len":      length,
39	"not":      not,
40	"or":       or,
41	"print":    fmt.Sprint,
42	"printf":   fmt.Sprintf,
43	"println":  fmt.Sprintln,
44	"urlquery": URLQueryEscaper,
45
46	// Comparisons
47	"eq": eq, // ==
48	"ge": ge, // >=
49	"gt": gt, // >
50	"le": le, // <=
51	"lt": lt, // <
52	"ne": ne, // !=
53}
54
55var builtinFuncs = createValueFuncs(builtins)
56
57// createValueFuncs turns a FuncMap into a map[string]reflect.Value
58func createValueFuncs(funcMap FuncMap) map[string]reflect.Value {
59	m := make(map[string]reflect.Value)
60	addValueFuncs(m, funcMap)
61	return m
62}
63
64// addValueFuncs adds to values the functions in funcs, converting them to reflect.Values.
65func addValueFuncs(out map[string]reflect.Value, in FuncMap) {
66	for name, fn := range in {
67		v := reflect.ValueOf(fn)
68		if v.Kind() != reflect.Func {
69			panic("value for " + name + " not a function")
70		}
71		if !goodFunc(v.Type()) {
72			panic(fmt.Errorf("can't install method/function %q with %d results", name, v.Type().NumOut()))
73		}
74		out[name] = v
75	}
76}
77
78// AddFuncs adds to values the functions in funcs. It does no checking of the input -
79// call addValueFuncs first.
80func addFuncs(out, in FuncMap) {
81	for name, fn := range in {
82		out[name] = fn
83	}
84}
85
86// goodFunc checks that the function or method has the right result signature.
87func goodFunc(typ reflect.Type) bool {
88	// We allow functions with 1 result or 2 results where the second is an error.
89	switch {
90	case typ.NumOut() == 1:
91		return true
92	case typ.NumOut() == 2 && typ.Out(1) == errorType:
93		return true
94	}
95	return false
96}
97
98// findFunction looks for a function in the template, and global map.
99func findFunction(name string) (reflect.Value, bool) {
100	if fn := builtinFuncs[name]; fn.IsValid() {
101		return fn, true
102	}
103	return reflect.Value{}, false
104}
105
106// Indexing.
107
108// index returns the result of indexing its first argument by the following
109// arguments.  Thus "index x 1 2 3" is, in Go syntax, x[1][2][3]. Each
110// indexed item must be a map, slice, or array.
111func index(item interface{}, indices ...interface{}) (interface{}, error) {
112	v := reflect.ValueOf(item)
113	for _, i := range indices {
114		index := reflect.ValueOf(i)
115		var isNil bool
116		if v, isNil = indirect(v); isNil {
117			return nil, fmt.Errorf("index of nil pointer")
118		}
119		switch v.Kind() {
120		case reflect.Array, reflect.Slice, reflect.String:
121			var x int64
122			switch index.Kind() {
123			case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
124				x = index.Int()
125			case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
126				x = int64(index.Uint())
127			default:
128				return nil, fmt.Errorf("cannot index slice/array with type %s", index.Type())
129			}
130			if x < 0 || x >= int64(v.Len()) {
131				return nil, fmt.Errorf("index out of range: %d", x)
132			}
133			v = v.Index(int(x))
134		case reflect.Map:
135			if !index.IsValid() {
136				index = reflect.Zero(v.Type().Key())
137			}
138			if !index.Type().AssignableTo(v.Type().Key()) {
139				return nil, fmt.Errorf("%s is not index type for %s", index.Type(), v.Type())
140			}
141			if x := v.MapIndex(index); x.IsValid() {
142				v = x
143			} else {
144				v = reflect.Zero(v.Type().Elem())
145			}
146		default:
147			return nil, fmt.Errorf("can't index item of type %s", v.Type())
148		}
149	}
150	return v.Interface(), nil
151}
152
153// Length
154
155// length returns the length of the item, with an error if it has no defined length.
156func length(item interface{}) (int, error) {
157	v, isNil := indirect(reflect.ValueOf(item))
158	if isNil {
159		return 0, fmt.Errorf("len of nil pointer")
160	}
161	switch v.Kind() {
162	case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice, reflect.String:
163		return v.Len(), nil
164	}
165	return 0, fmt.Errorf("len of type %s", v.Type())
166}
167
168// Function invocation
169
170// call returns the result of evaluating the first argument as a function.
171// The function must return 1 result, or 2 results, the second of which is an error.
172func call(fn interface{}, args ...interface{}) (interface{}, error) {
173	v := reflect.ValueOf(fn)
174	typ := v.Type()
175	if typ.Kind() != reflect.Func {
176		return nil, fmt.Errorf("non-function of type %s", typ)
177	}
178	if !goodFunc(typ) {
179		return nil, fmt.Errorf("function called with %d args; should be 1 or 2", typ.NumOut())
180	}
181	numIn := typ.NumIn()
182	var dddType reflect.Type
183	if typ.IsVariadic() {
184		if len(args) < numIn-1 {
185			return nil, fmt.Errorf("wrong number of args: got %d want at least %d", len(args), numIn-1)
186		}
187		dddType = typ.In(numIn - 1).Elem()
188	} else {
189		if len(args) != numIn {
190			return nil, fmt.Errorf("wrong number of args: got %d want %d", len(args), numIn)
191		}
192	}
193	argv := make([]reflect.Value, len(args))
194	for i, arg := range args {
195		value := reflect.ValueOf(arg)
196		// Compute the expected type. Clumsy because of variadics.
197		var argType reflect.Type
198		if !typ.IsVariadic() || i < numIn-1 {
199			argType = typ.In(i)
200		} else {
201			argType = dddType
202		}
203		if !value.IsValid() && canBeNil(argType) {
204			value = reflect.Zero(argType)
205		}
206		if !value.Type().AssignableTo(argType) {
207			return nil, fmt.Errorf("arg %d has type %s; should be %s", i, value.Type(), argType)
208		}
209		argv[i] = value
210	}
211	result := v.Call(argv)
212	if len(result) == 2 && !result[1].IsNil() {
213		return result[0].Interface(), result[1].Interface().(error)
214	}
215	return result[0].Interface(), nil
216}
217
218// Boolean logic.
219
220func truth(a interface{}) bool {
221	t, _ := isTrue(reflect.ValueOf(a))
222	return t
223}
224
225// and computes the Boolean AND of its arguments, returning
226// the first false argument it encounters, or the last argument.
227func and(arg0 interface{}, args ...interface{}) interface{} {
228	if !truth(arg0) {
229		return arg0
230	}
231	for i := range args {
232		arg0 = args[i]
233		if !truth(arg0) {
234			break
235		}
236	}
237	return arg0
238}
239
240// or computes the Boolean OR of its arguments, returning
241// the first true argument it encounters, or the last argument.
242func or(arg0 interface{}, args ...interface{}) interface{} {
243	if truth(arg0) {
244		return arg0
245	}
246	for i := range args {
247		arg0 = args[i]
248		if truth(arg0) {
249			break
250		}
251	}
252	return arg0
253}
254
255// not returns the Boolean negation of its argument.
256func not(arg interface{}) (truth bool) {
257	truth, _ = isTrue(reflect.ValueOf(arg))
258	return !truth
259}
260
261// Comparison.
262
263// TODO: Perhaps allow comparison between signed and unsigned integers.
264
265var (
266	errBadComparisonType = errors.New("invalid type for comparison")
267	errBadComparison     = errors.New("incompatible types for comparison")
268	errNoComparison      = errors.New("missing argument for comparison")
269)
270
271type kind int
272
273const (
274	invalidKind kind = iota
275	boolKind
276	complexKind
277	intKind
278	floatKind
279	integerKind
280	stringKind
281	uintKind
282)
283
284func basicKind(v reflect.Value) (kind, error) {
285	switch v.Kind() {
286	case reflect.Bool:
287		return boolKind, nil
288	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
289		return intKind, nil
290	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
291		return uintKind, nil
292	case reflect.Float32, reflect.Float64:
293		return floatKind, nil
294	case reflect.Complex64, reflect.Complex128:
295		return complexKind, nil
296	case reflect.String:
297		return stringKind, nil
298	}
299	return invalidKind, errBadComparisonType
300}
301
302// eq evaluates the comparison a == b || a == c || ...
303func eq(arg1 interface{}, arg2 ...interface{}) (bool, error) {
304	v1 := reflect.ValueOf(arg1)
305	k1, err := basicKind(v1)
306	if err != nil {
307		return false, err
308	}
309	if len(arg2) == 0 {
310		return false, errNoComparison
311	}
312	for _, arg := range arg2 {
313		v2 := reflect.ValueOf(arg)
314		k2, err := basicKind(v2)
315		if err != nil {
316			return false, err
317		}
318		truth := false
319		if k1 != k2 {
320			// Special case: Can compare integer values regardless of type's sign.
321			switch {
322			case k1 == intKind && k2 == uintKind:
323				truth = v1.Int() >= 0 && uint64(v1.Int()) == v2.Uint()
324			case k1 == uintKind && k2 == intKind:
325				truth = v2.Int() >= 0 && v1.Uint() == uint64(v2.Int())
326			default:
327				return false, errBadComparison
328			}
329		} else {
330			switch k1 {
331			case boolKind:
332				truth = v1.Bool() == v2.Bool()
333			case complexKind:
334				truth = v1.Complex() == v2.Complex()
335			case floatKind:
336				truth = v1.Float() == v2.Float()
337			case intKind:
338				truth = v1.Int() == v2.Int()
339			case stringKind:
340				truth = v1.String() == v2.String()
341			case uintKind:
342				truth = v1.Uint() == v2.Uint()
343			default:
344				panic("invalid kind")
345			}
346		}
347		if truth {
348			return true, nil
349		}
350	}
351	return false, nil
352}
353
354// ne evaluates the comparison a != b.
355func ne(arg1, arg2 interface{}) (bool, error) {
356	// != is the inverse of ==.
357	equal, err := eq(arg1, arg2)
358	return !equal, err
359}
360
361// lt evaluates the comparison a < b.
362func lt(arg1, arg2 interface{}) (bool, error) {
363	v1 := reflect.ValueOf(arg1)
364	k1, err := basicKind(v1)
365	if err != nil {
366		return false, err
367	}
368	v2 := reflect.ValueOf(arg2)
369	k2, err := basicKind(v2)
370	if err != nil {
371		return false, err
372	}
373	truth := false
374	if k1 != k2 {
375		// Special case: Can compare integer values regardless of type's sign.
376		switch {
377		case k1 == intKind && k2 == uintKind:
378			truth = v1.Int() < 0 || uint64(v1.Int()) < v2.Uint()
379		case k1 == uintKind && k2 == intKind:
380			truth = v2.Int() >= 0 && v1.Uint() < uint64(v2.Int())
381		default:
382			return false, errBadComparison
383		}
384	} else {
385		switch k1 {
386		case boolKind, complexKind:
387			return false, errBadComparisonType
388		case floatKind:
389			truth = v1.Float() < v2.Float()
390		case intKind:
391			truth = v1.Int() < v2.Int()
392		case stringKind:
393			truth = v1.String() < v2.String()
394		case uintKind:
395			truth = v1.Uint() < v2.Uint()
396		default:
397			panic("invalid kind")
398		}
399	}
400	return truth, nil
401}
402
403// le evaluates the comparison <= b.
404func le(arg1, arg2 interface{}) (bool, error) {
405	// <= is < or ==.
406	lessThan, err := lt(arg1, arg2)
407	if lessThan || err != nil {
408		return lessThan, err
409	}
410	return eq(arg1, arg2)
411}
412
413// gt evaluates the comparison a > b.
414func gt(arg1, arg2 interface{}) (bool, error) {
415	// > is the inverse of <=.
416	lessOrEqual, err := le(arg1, arg2)
417	if err != nil {
418		return false, err
419	}
420	return !lessOrEqual, nil
421}
422
423// ge evaluates the comparison a >= b.
424func ge(arg1, arg2 interface{}) (bool, error) {
425	// >= is the inverse of <.
426	lessThan, err := lt(arg1, arg2)
427	if err != nil {
428		return false, err
429	}
430	return !lessThan, nil
431}
432
433// HTML escaping.
434
435var (
436	htmlQuot = []byte("&#34;") // shorter than "&quot;"
437	htmlApos = []byte("&#39;") // shorter than "&apos;" and apos was not in HTML until HTML5
438	htmlAmp  = []byte("&amp;")
439	htmlLt   = []byte("&lt;")
440	htmlGt   = []byte("&gt;")
441)
442
443// HTMLEscape writes to w the escaped HTML equivalent of the plain text data b.
444func HTMLEscape(w io.Writer, b []byte) {
445	last := 0
446	for i, c := range b {
447		var html []byte
448		switch c {
449		case '"':
450			html = htmlQuot
451		case '\'':
452			html = htmlApos
453		case '&':
454			html = htmlAmp
455		case '<':
456			html = htmlLt
457		case '>':
458			html = htmlGt
459		default:
460			continue
461		}
462		w.Write(b[last:i])
463		w.Write(html)
464		last = i + 1
465	}
466	w.Write(b[last:])
467}
468
469// HTMLEscapeString returns the escaped HTML equivalent of the plain text data s.
470func HTMLEscapeString(s string) string {
471	// Avoid allocation if we can.
472	if strings.IndexAny(s, `'"&<>`) < 0 {
473		return s
474	}
475	var b bytes.Buffer
476	HTMLEscape(&b, []byte(s))
477	return b.String()
478}
479
480// HTMLEscaper returns the escaped HTML equivalent of the textual
481// representation of its arguments.
482func HTMLEscaper(args ...interface{}) string {
483	return HTMLEscapeString(evalArgs(args))
484}
485
486// JavaScript escaping.
487
488var (
489	jsLowUni = []byte(`\u00`)
490	hex      = []byte("0123456789ABCDEF")
491
492	jsBackslash = []byte(`\\`)
493	jsApos      = []byte(`\'`)
494	jsQuot      = []byte(`\"`)
495	jsLt        = []byte(`\x3C`)
496	jsGt        = []byte(`\x3E`)
497)
498
499// JSEscape writes to w the escaped JavaScript equivalent of the plain text data b.
500func JSEscape(w io.Writer, b []byte) {
501	last := 0
502	for i := 0; i < len(b); i++ {
503		c := b[i]
504
505		if !jsIsSpecial(rune(c)) {
506			// fast path: nothing to do
507			continue
508		}
509		w.Write(b[last:i])
510
511		if c < utf8.RuneSelf {
512			// Quotes, slashes and angle brackets get quoted.
513			// Control characters get written as \u00XX.
514			switch c {
515			case '\\':
516				w.Write(jsBackslash)
517			case '\'':
518				w.Write(jsApos)
519			case '"':
520				w.Write(jsQuot)
521			case '<':
522				w.Write(jsLt)
523			case '>':
524				w.Write(jsGt)
525			default:
526				w.Write(jsLowUni)
527				t, b := c>>4, c&0x0f
528				w.Write(hex[t : t+1])
529				w.Write(hex[b : b+1])
530			}
531		} else {
532			// Unicode rune.
533			r, size := utf8.DecodeRune(b[i:])
534			if unicode.IsPrint(r) {
535				w.Write(b[i : i+size])
536			} else {
537				fmt.Fprintf(w, "\\u%04X", r)
538			}
539			i += size - 1
540		}
541		last = i + 1
542	}
543	w.Write(b[last:])
544}
545
546// JSEscapeString returns the escaped JavaScript equivalent of the plain text data s.
547func JSEscapeString(s string) string {
548	// Avoid allocation if we can.
549	if strings.IndexFunc(s, jsIsSpecial) < 0 {
550		return s
551	}
552	var b bytes.Buffer
553	JSEscape(&b, []byte(s))
554	return b.String()
555}
556
557func jsIsSpecial(r rune) bool {
558	switch r {
559	case '\\', '\'', '"', '<', '>':
560		return true
561	}
562	return r < ' ' || utf8.RuneSelf <= r
563}
564
565// JSEscaper returns the escaped JavaScript equivalent of the textual
566// representation of its arguments.
567func JSEscaper(args ...interface{}) string {
568	return JSEscapeString(evalArgs(args))
569}
570
571// URLQueryEscaper returns the escaped value of the textual representation of
572// its arguments in a form suitable for embedding in a URL query.
573func URLQueryEscaper(args ...interface{}) string {
574	return url.QueryEscape(evalArgs(args))
575}
576
577// evalArgs formats the list of arguments into a string. It is therefore equivalent to
578//	fmt.Sprint(args...)
579// except that each argument is indirected (if a pointer), as required,
580// using the same rules as the default string evaluation during template
581// execution.
582func evalArgs(args []interface{}) string {
583	ok := false
584	var s string
585	// Fast path for simple common case.
586	if len(args) == 1 {
587		s, ok = args[0].(string)
588	}
589	if !ok {
590		for i, arg := range args {
591			a, ok := printableValue(reflect.ValueOf(arg))
592			if ok {
593				args[i] = a
594			} // else left fmt do its thing
595		}
596		s = fmt.Sprint(args...)
597	}
598	return s
599}
600