Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
0.00% |
0 / 38 |
|
0.00% |
0 / 2 |
CRAP | |
0.00% |
0 / 1 |
| AccessConditionExpression | |
0.00% |
0 / 38 |
|
0.00% |
0 / 2 |
110 | |
0.00% |
0 / 1 |
| __construct | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
| evaluateCondition | |
0.00% |
0 / 32 |
|
0.00% |
0 / 1 |
90 | |||
| 1 | <?php |
| 2 | |
| 3 | /******************* |
| 4 | |
| 5 | DO NOT CHANGE! This is a core UserFrosting file, and should not need to be changed by developers. |
| 6 | |
| 7 | ********************/ |
| 8 | |
| 9 | namespace UserFrosting; |
| 10 | |
| 11 | use PhpParser\Node; |
| 12 | use PhpParser\ParserFactory; |
| 13 | |
| 14 | // Models the evaluation of an authorization condition expression, which is built as a boolean expression composed of AccessCondition method calls. |
| 15 | class AccessConditionExpression { |
| 16 | |
| 17 | protected $_app; // The framework app to use (default Slim) |
| 18 | protected $_parser; |
| 19 | protected $_traverser; |
| 20 | protected $_prettyPrinter; |
| 21 | protected $_debug; |
| 22 | |
| 23 | public function __construct($app, $debug = false){ |
| 24 | // Use ParserFactory to create a parser instance |
| 25 | $parserFactory = new ParserFactory; |
| 26 | $this->_parser = $parserFactory->createForNewestSupportedVersion(); |
| 27 | |
| 28 | $this->_traverser = new \PhpParser\NodeTraverser; |
| 29 | $this->_prettyPrinter = new \PhpParser\PrettyPrinter\Standard; |
| 30 | $this->_debug = $debug; |
| 31 | $this->_app = $app; |
| 32 | } |
| 33 | |
| 34 | // Evaluates a condition expression, based on the given parameters. Returns true if the condition is passed for the given parameters, otherwise returns false. |
| 35 | public function evaluateCondition($condition, $params){ |
| 36 | // Set the reserved `self` and `route` parameters. |
| 37 | // This replaces any values of `self` or `route` specified in the arguments, thus preventing them from being overridden in malicious user input. |
| 38 | $params['self'] = $this->_app->user->export(); |
| 39 | |
| 40 | $route = $this->_app->router()->getCurrentRoute(); |
| 41 | $params['route'] = $route->getParams(); |
| 42 | |
| 43 | /* Traverse the parse tree, and execute all function calls as methods of class AccessCondition. |
| 44 | Replace the function node with the return value of the method. |
| 45 | */ |
| 46 | $pv = new \ParserNodeFunctionEvaluator($params, $this->_debug); |
| 47 | $this->_traverser->addVisitor($pv); |
| 48 | |
| 49 | $code = "<?php $condition;"; |
| 50 | |
| 51 | if ($this->_debug){ |
| 52 | error_log("<pre>Evaluating access conditions:\n"); |
| 53 | error_log($condition. "\n\n". |
| 54 | "on params: \n" . |
| 55 | print_r($params, true) . "\n" . |
| 56 | "</pre>"); |
| 57 | } |
| 58 | |
| 59 | try { |
| 60 | |
| 61 | // parse |
| 62 | $stmts = $this->_parser->parse($code); |
| 63 | |
| 64 | // traverse |
| 65 | $stmts = $this->_traverser->traverse($stmts); |
| 66 | |
| 67 | // Evaluate boolean statement. It is safe to use eval() here, because our expression has been reduced entirely to a boolean expression. |
| 68 | // In PHP Parser 5.x, we need to extract the expression from the statement |
| 69 | $stmt = $stmts[0]; |
| 70 | $expr = null; |
| 71 | |
| 72 | // Check if we have a Statement\Expression node and extract the expression |
| 73 | if ($stmt instanceof \PhpParser\Node\Stmt\Expression) { |
| 74 | $expr = $this->_prettyPrinter->prettyPrintExpr($stmt->expr); |
| 75 | } else { |
| 76 | // Fallback for other node types |
| 77 | $expr = $this->_prettyPrinter->prettyPrint([$stmt]); |
| 78 | } |
| 79 | |
| 80 | $expr_eval = "return " . $expr . ";\n"; |
| 81 | $result = eval($expr_eval); |
| 82 | |
| 83 | if ($this->_debug){ |
| 84 | error_log("<pre>\"$expr\" evaluates to " . ($result == true ? "true" : "false") . "</pre>"); |
| 85 | } |
| 86 | |
| 87 | return $result; |
| 88 | } catch (\PhpParser\Error $e) { |
| 89 | if ($this->_debug){ |
| 90 | error_log("Error parsing access condition \"$condition\": \n" . $e->getMessage()); |
| 91 | } |
| 92 | return false; // Access fails if the access condition can't be parsed. |
| 93 | } catch (\UserFrosting\AuthorizationException $e) { |
| 94 | if ($this->_debug){ |
| 95 | error_log("Error parsing access condition \"$condition\": \n" . $e->getMessage()); |
| 96 | } |
| 97 | return false; |
| 98 | } |
| 99 | } |
| 100 | |
| 101 | } |