variable.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682
  1. package pongo2
  2. import (
  3. "fmt"
  4. "reflect"
  5. "strconv"
  6. "strings"
  7. "github.com/juju/errors"
  8. )
  9. const (
  10. varTypeInt = iota
  11. varTypeIdent
  12. )
  13. var (
  14. typeOfValuePtr = reflect.TypeOf(new(Value))
  15. typeOfExecCtxPtr = reflect.TypeOf(new(ExecutionContext))
  16. )
  17. type variablePart struct {
  18. typ int
  19. s string
  20. i int
  21. isFunctionCall bool
  22. callingArgs []functionCallArgument // needed for a function call, represents all argument nodes (INode supports nested function calls)
  23. }
  24. type functionCallArgument interface {
  25. Evaluate(*ExecutionContext) (*Value, *Error)
  26. }
  27. // TODO: Add location tokens
  28. type stringResolver struct {
  29. locationToken *Token
  30. val string
  31. }
  32. type intResolver struct {
  33. locationToken *Token
  34. val int
  35. }
  36. type floatResolver struct {
  37. locationToken *Token
  38. val float64
  39. }
  40. type boolResolver struct {
  41. locationToken *Token
  42. val bool
  43. }
  44. type variableResolver struct {
  45. locationToken *Token
  46. parts []*variablePart
  47. }
  48. type nodeFilteredVariable struct {
  49. locationToken *Token
  50. resolver IEvaluator
  51. filterChain []*filterCall
  52. }
  53. type nodeVariable struct {
  54. locationToken *Token
  55. expr IEvaluator
  56. }
  57. type executionCtxEval struct{}
  58. func (v *nodeFilteredVariable) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
  59. value, err := v.Evaluate(ctx)
  60. if err != nil {
  61. return err
  62. }
  63. writer.WriteString(value.String())
  64. return nil
  65. }
  66. func (vr *variableResolver) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
  67. value, err := vr.Evaluate(ctx)
  68. if err != nil {
  69. return err
  70. }
  71. writer.WriteString(value.String())
  72. return nil
  73. }
  74. func (s *stringResolver) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
  75. value, err := s.Evaluate(ctx)
  76. if err != nil {
  77. return err
  78. }
  79. writer.WriteString(value.String())
  80. return nil
  81. }
  82. func (i *intResolver) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
  83. value, err := i.Evaluate(ctx)
  84. if err != nil {
  85. return err
  86. }
  87. writer.WriteString(value.String())
  88. return nil
  89. }
  90. func (f *floatResolver) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
  91. value, err := f.Evaluate(ctx)
  92. if err != nil {
  93. return err
  94. }
  95. writer.WriteString(value.String())
  96. return nil
  97. }
  98. func (b *boolResolver) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
  99. value, err := b.Evaluate(ctx)
  100. if err != nil {
  101. return err
  102. }
  103. writer.WriteString(value.String())
  104. return nil
  105. }
  106. func (v *nodeFilteredVariable) GetPositionToken() *Token {
  107. return v.locationToken
  108. }
  109. func (vr *variableResolver) GetPositionToken() *Token {
  110. return vr.locationToken
  111. }
  112. func (s *stringResolver) GetPositionToken() *Token {
  113. return s.locationToken
  114. }
  115. func (i *intResolver) GetPositionToken() *Token {
  116. return i.locationToken
  117. }
  118. func (f *floatResolver) GetPositionToken() *Token {
  119. return f.locationToken
  120. }
  121. func (b *boolResolver) GetPositionToken() *Token {
  122. return b.locationToken
  123. }
  124. func (s *stringResolver) Evaluate(ctx *ExecutionContext) (*Value, *Error) {
  125. return AsValue(s.val), nil
  126. }
  127. func (i *intResolver) Evaluate(ctx *ExecutionContext) (*Value, *Error) {
  128. return AsValue(i.val), nil
  129. }
  130. func (f *floatResolver) Evaluate(ctx *ExecutionContext) (*Value, *Error) {
  131. return AsValue(f.val), nil
  132. }
  133. func (b *boolResolver) Evaluate(ctx *ExecutionContext) (*Value, *Error) {
  134. return AsValue(b.val), nil
  135. }
  136. func (s *stringResolver) FilterApplied(name string) bool {
  137. return false
  138. }
  139. func (i *intResolver) FilterApplied(name string) bool {
  140. return false
  141. }
  142. func (f *floatResolver) FilterApplied(name string) bool {
  143. return false
  144. }
  145. func (b *boolResolver) FilterApplied(name string) bool {
  146. return false
  147. }
  148. func (nv *nodeVariable) FilterApplied(name string) bool {
  149. return nv.expr.FilterApplied(name)
  150. }
  151. func (nv *nodeVariable) Execute(ctx *ExecutionContext, writer TemplateWriter) *Error {
  152. value, err := nv.expr.Evaluate(ctx)
  153. if err != nil {
  154. return err
  155. }
  156. if !nv.expr.FilterApplied("safe") && !value.safe && value.IsString() && ctx.Autoescape {
  157. // apply escape filter
  158. value, err = filters["escape"](value, nil)
  159. if err != nil {
  160. return err
  161. }
  162. }
  163. writer.WriteString(value.String())
  164. return nil
  165. }
  166. func (executionCtxEval) Evaluate(ctx *ExecutionContext) (*Value, *Error) {
  167. return AsValue(ctx), nil
  168. }
  169. func (vr *variableResolver) FilterApplied(name string) bool {
  170. return false
  171. }
  172. func (vr *variableResolver) String() string {
  173. parts := make([]string, 0, len(vr.parts))
  174. for _, p := range vr.parts {
  175. switch p.typ {
  176. case varTypeInt:
  177. parts = append(parts, strconv.Itoa(p.i))
  178. case varTypeIdent:
  179. parts = append(parts, p.s)
  180. default:
  181. panic("unimplemented")
  182. }
  183. }
  184. return strings.Join(parts, ".")
  185. }
  186. func (vr *variableResolver) resolve(ctx *ExecutionContext) (*Value, error) {
  187. var current reflect.Value
  188. var isSafe bool
  189. for idx, part := range vr.parts {
  190. if idx == 0 {
  191. // We're looking up the first part of the variable.
  192. // First we're having a look in our private
  193. // context (e. g. information provided by tags, like the forloop)
  194. val, inPrivate := ctx.Private[vr.parts[0].s]
  195. if !inPrivate {
  196. // Nothing found? Then have a final lookup in the public context
  197. val = ctx.Public[vr.parts[0].s]
  198. }
  199. current = reflect.ValueOf(val) // Get the initial value
  200. } else {
  201. // Next parts, resolve it from current
  202. // Before resolving the pointer, let's see if we have a method to call
  203. // Problem with resolving the pointer is we're changing the receiver
  204. isFunc := false
  205. if part.typ == varTypeIdent {
  206. funcValue := current.MethodByName(part.s)
  207. if funcValue.IsValid() {
  208. current = funcValue
  209. isFunc = true
  210. }
  211. }
  212. if !isFunc {
  213. // If current a pointer, resolve it
  214. if current.Kind() == reflect.Ptr {
  215. current = current.Elem()
  216. if !current.IsValid() {
  217. // Value is not valid (anymore)
  218. return AsValue(nil), nil
  219. }
  220. }
  221. // Look up which part must be called now
  222. switch part.typ {
  223. case varTypeInt:
  224. // Calling an index is only possible for:
  225. // * slices/arrays/strings
  226. switch current.Kind() {
  227. case reflect.String, reflect.Array, reflect.Slice:
  228. if part.i >= 0 && current.Len() > part.i {
  229. current = current.Index(part.i)
  230. } else {
  231. // In Django, exceeding the length of a list is just empty.
  232. return AsValue(nil), nil
  233. }
  234. default:
  235. return nil, errors.Errorf("Can't access an index on type %s (variable %s)",
  236. current.Kind().String(), vr.String())
  237. }
  238. case varTypeIdent:
  239. // debugging:
  240. // fmt.Printf("now = %s (kind: %s)\n", part.s, current.Kind().String())
  241. // Calling a field or key
  242. switch current.Kind() {
  243. case reflect.Struct:
  244. current = current.FieldByName(part.s)
  245. case reflect.Map:
  246. current = current.MapIndex(reflect.ValueOf(part.s))
  247. default:
  248. return nil, errors.Errorf("Can't access a field by name on type %s (variable %s)",
  249. current.Kind().String(), vr.String())
  250. }
  251. default:
  252. panic("unimplemented")
  253. }
  254. }
  255. }
  256. if !current.IsValid() {
  257. // Value is not valid (anymore)
  258. return AsValue(nil), nil
  259. }
  260. // If current is a reflect.ValueOf(pongo2.Value), then unpack it
  261. // Happens in function calls (as a return value) or by injecting
  262. // into the execution context (e.g. in a for-loop)
  263. if current.Type() == typeOfValuePtr {
  264. tmpValue := current.Interface().(*Value)
  265. current = tmpValue.val
  266. isSafe = tmpValue.safe
  267. }
  268. // Check whether this is an interface and resolve it where required
  269. if current.Kind() == reflect.Interface {
  270. current = reflect.ValueOf(current.Interface())
  271. }
  272. // Check if the part is a function call
  273. if part.isFunctionCall || current.Kind() == reflect.Func {
  274. // Check for callable
  275. if current.Kind() != reflect.Func {
  276. return nil, errors.Errorf("'%s' is not a function (it is %s)", vr.String(), current.Kind().String())
  277. }
  278. // Check for correct function syntax and types
  279. // func(*Value, ...) *Value
  280. t := current.Type()
  281. currArgs := part.callingArgs
  282. // If an implicit ExecCtx is needed
  283. if t.NumIn() > 0 && t.In(0) == typeOfExecCtxPtr {
  284. currArgs = append([]functionCallArgument{executionCtxEval{}}, currArgs...)
  285. }
  286. // Input arguments
  287. if len(currArgs) != t.NumIn() && !(len(currArgs) >= t.NumIn()-1 && t.IsVariadic()) {
  288. return nil,
  289. errors.Errorf("Function input argument count (%d) of '%s' must be equal to the calling argument count (%d).",
  290. t.NumIn(), vr.String(), len(currArgs))
  291. }
  292. // Output arguments
  293. if t.NumOut() != 1 {
  294. return nil, errors.Errorf("'%s' must have exactly 1 output argument", vr.String())
  295. }
  296. // Evaluate all parameters
  297. var parameters []reflect.Value
  298. numArgs := t.NumIn()
  299. isVariadic := t.IsVariadic()
  300. var fnArg reflect.Type
  301. for idx, arg := range currArgs {
  302. pv, err := arg.Evaluate(ctx)
  303. if err != nil {
  304. return nil, err
  305. }
  306. if isVariadic {
  307. if idx >= t.NumIn()-1 {
  308. fnArg = t.In(numArgs - 1).Elem()
  309. } else {
  310. fnArg = t.In(idx)
  311. }
  312. } else {
  313. fnArg = t.In(idx)
  314. }
  315. if fnArg != typeOfValuePtr {
  316. // Function's argument is not a *pongo2.Value, then we have to check whether input argument is of the same type as the function's argument
  317. if !isVariadic {
  318. if fnArg != reflect.TypeOf(pv.Interface()) && fnArg.Kind() != reflect.Interface {
  319. return nil, errors.Errorf("Function input argument %d of '%s' must be of type %s or *pongo2.Value (not %T).",
  320. idx, vr.String(), fnArg.String(), pv.Interface())
  321. }
  322. // Function's argument has another type, using the interface-value
  323. parameters = append(parameters, reflect.ValueOf(pv.Interface()))
  324. } else {
  325. if fnArg != reflect.TypeOf(pv.Interface()) && fnArg.Kind() != reflect.Interface {
  326. return nil, errors.Errorf("Function variadic input argument of '%s' must be of type %s or *pongo2.Value (not %T).",
  327. vr.String(), fnArg.String(), pv.Interface())
  328. }
  329. // Function's argument has another type, using the interface-value
  330. parameters = append(parameters, reflect.ValueOf(pv.Interface()))
  331. }
  332. } else {
  333. // Function's argument is a *pongo2.Value
  334. parameters = append(parameters, reflect.ValueOf(pv))
  335. }
  336. }
  337. // Check if any of the values are invalid
  338. for _, p := range parameters {
  339. if p.Kind() == reflect.Invalid {
  340. return nil, errors.Errorf("Calling a function using an invalid parameter")
  341. }
  342. }
  343. // Call it and get first return parameter back
  344. rv := current.Call(parameters)[0]
  345. if rv.Type() != typeOfValuePtr {
  346. current = reflect.ValueOf(rv.Interface())
  347. } else {
  348. // Return the function call value
  349. current = rv.Interface().(*Value).val
  350. isSafe = rv.Interface().(*Value).safe
  351. }
  352. }
  353. if !current.IsValid() {
  354. // Value is not valid (e. g. NIL value)
  355. return AsValue(nil), nil
  356. }
  357. }
  358. return &Value{val: current, safe: isSafe}, nil
  359. }
  360. func (vr *variableResolver) Evaluate(ctx *ExecutionContext) (*Value, *Error) {
  361. value, err := vr.resolve(ctx)
  362. if err != nil {
  363. return AsValue(nil), ctx.Error(err.Error(), vr.locationToken)
  364. }
  365. return value, nil
  366. }
  367. func (v *nodeFilteredVariable) FilterApplied(name string) bool {
  368. for _, filter := range v.filterChain {
  369. if filter.name == name {
  370. return true
  371. }
  372. }
  373. return false
  374. }
  375. func (v *nodeFilteredVariable) Evaluate(ctx *ExecutionContext) (*Value, *Error) {
  376. value, err := v.resolver.Evaluate(ctx)
  377. if err != nil {
  378. return nil, err
  379. }
  380. for _, filter := range v.filterChain {
  381. value, err = filter.Execute(value, ctx)
  382. if err != nil {
  383. return nil, err
  384. }
  385. }
  386. return value, nil
  387. }
  388. // IDENT | IDENT.(IDENT|NUMBER)...
  389. func (p *Parser) parseVariableOrLiteral() (IEvaluator, *Error) {
  390. t := p.Current()
  391. if t == nil {
  392. return nil, p.Error("Unexpected EOF, expected a number, string, keyword or identifier.", p.lastToken)
  393. }
  394. // Is first part a number or a string, there's nothing to resolve (because there's only to return the value then)
  395. switch t.Typ {
  396. case TokenNumber:
  397. p.Consume()
  398. // One exception to the rule that we don't have float64 literals is at the beginning
  399. // of an expression (or a variable name). Since we know we started with an integer
  400. // which can't obviously be a variable name, we can check whether the first number
  401. // is followed by dot (and then a number again). If so we're converting it to a float64.
  402. if p.Match(TokenSymbol, ".") != nil {
  403. // float64
  404. t2 := p.MatchType(TokenNumber)
  405. if t2 == nil {
  406. return nil, p.Error("Expected a number after the '.'.", nil)
  407. }
  408. f, err := strconv.ParseFloat(fmt.Sprintf("%s.%s", t.Val, t2.Val), 64)
  409. if err != nil {
  410. return nil, p.Error(err.Error(), t)
  411. }
  412. fr := &floatResolver{
  413. locationToken: t,
  414. val: f,
  415. }
  416. return fr, nil
  417. }
  418. i, err := strconv.Atoi(t.Val)
  419. if err != nil {
  420. return nil, p.Error(err.Error(), t)
  421. }
  422. nr := &intResolver{
  423. locationToken: t,
  424. val: i,
  425. }
  426. return nr, nil
  427. case TokenString:
  428. p.Consume()
  429. sr := &stringResolver{
  430. locationToken: t,
  431. val: t.Val,
  432. }
  433. return sr, nil
  434. case TokenKeyword:
  435. p.Consume()
  436. switch t.Val {
  437. case "true":
  438. br := &boolResolver{
  439. locationToken: t,
  440. val: true,
  441. }
  442. return br, nil
  443. case "false":
  444. br := &boolResolver{
  445. locationToken: t,
  446. val: false,
  447. }
  448. return br, nil
  449. default:
  450. return nil, p.Error("This keyword is not allowed here.", nil)
  451. }
  452. }
  453. resolver := &variableResolver{
  454. locationToken: t,
  455. }
  456. // First part of a variable MUST be an identifier
  457. if t.Typ != TokenIdentifier {
  458. return nil, p.Error("Expected either a number, string, keyword or identifier.", t)
  459. }
  460. resolver.parts = append(resolver.parts, &variablePart{
  461. typ: varTypeIdent,
  462. s: t.Val,
  463. })
  464. p.Consume() // we consumed the first identifier of the variable name
  465. variableLoop:
  466. for p.Remaining() > 0 {
  467. t = p.Current()
  468. if p.Match(TokenSymbol, ".") != nil {
  469. // Next variable part (can be either NUMBER or IDENT)
  470. t2 := p.Current()
  471. if t2 != nil {
  472. switch t2.Typ {
  473. case TokenIdentifier:
  474. resolver.parts = append(resolver.parts, &variablePart{
  475. typ: varTypeIdent,
  476. s: t2.Val,
  477. })
  478. p.Consume() // consume: IDENT
  479. continue variableLoop
  480. case TokenNumber:
  481. i, err := strconv.Atoi(t2.Val)
  482. if err != nil {
  483. return nil, p.Error(err.Error(), t2)
  484. }
  485. resolver.parts = append(resolver.parts, &variablePart{
  486. typ: varTypeInt,
  487. i: i,
  488. })
  489. p.Consume() // consume: NUMBER
  490. continue variableLoop
  491. default:
  492. return nil, p.Error("This token is not allowed within a variable name.", t2)
  493. }
  494. } else {
  495. // EOF
  496. return nil, p.Error("Unexpected EOF, expected either IDENTIFIER or NUMBER after DOT.",
  497. p.lastToken)
  498. }
  499. } else if p.Match(TokenSymbol, "(") != nil {
  500. // Function call
  501. // FunctionName '(' Comma-separated list of expressions ')'
  502. part := resolver.parts[len(resolver.parts)-1]
  503. part.isFunctionCall = true
  504. argumentLoop:
  505. for {
  506. if p.Remaining() == 0 {
  507. return nil, p.Error("Unexpected EOF, expected function call argument list.", p.lastToken)
  508. }
  509. if p.Peek(TokenSymbol, ")") == nil {
  510. // No closing bracket, so we're parsing an expression
  511. exprArg, err := p.ParseExpression()
  512. if err != nil {
  513. return nil, err
  514. }
  515. part.callingArgs = append(part.callingArgs, exprArg)
  516. if p.Match(TokenSymbol, ")") != nil {
  517. // If there's a closing bracket after an expression, we will stop parsing the arguments
  518. break argumentLoop
  519. } else {
  520. // If there's NO closing bracket, there MUST be an comma
  521. if p.Match(TokenSymbol, ",") == nil {
  522. return nil, p.Error("Missing comma or closing bracket after argument.", nil)
  523. }
  524. }
  525. } else {
  526. // We got a closing bracket, so stop parsing arguments
  527. p.Consume()
  528. break argumentLoop
  529. }
  530. }
  531. // We're done parsing the function call, next variable part
  532. continue variableLoop
  533. }
  534. // No dot or function call? Then we're done with the variable parsing
  535. break
  536. }
  537. return resolver, nil
  538. }
  539. func (p *Parser) parseVariableOrLiteralWithFilter() (*nodeFilteredVariable, *Error) {
  540. v := &nodeFilteredVariable{
  541. locationToken: p.Current(),
  542. }
  543. // Parse the variable name
  544. resolver, err := p.parseVariableOrLiteral()
  545. if err != nil {
  546. return nil, err
  547. }
  548. v.resolver = resolver
  549. // Parse all the filters
  550. filterLoop:
  551. for p.Match(TokenSymbol, "|") != nil {
  552. // Parse one single filter
  553. filter, err := p.parseFilter()
  554. if err != nil {
  555. return nil, err
  556. }
  557. // Check sandbox filter restriction
  558. if _, isBanned := p.template.set.bannedFilters[filter.name]; isBanned {
  559. return nil, p.Error(fmt.Sprintf("Usage of filter '%s' is not allowed (sandbox restriction active).", filter.name), nil)
  560. }
  561. v.filterChain = append(v.filterChain, filter)
  562. continue filterLoop
  563. }
  564. return v, nil
  565. }
  566. func (p *Parser) parseVariableElement() (INode, *Error) {
  567. node := &nodeVariable{
  568. locationToken: p.Current(),
  569. }
  570. p.Consume() // consume '{{'
  571. expr, err := p.ParseExpression()
  572. if err != nil {
  573. return nil, err
  574. }
  575. node.expr = expr
  576. if p.Match(TokenSymbol, "}}") == nil {
  577. return nil, p.Error("'}}' expected", nil)
  578. }
  579. return node, nil
  580. }