Last active
December 24, 2015 07:19
-
-
Save maryo/6762610 to your computer and use it in GitHub Desktop.
Doctrine2 Sandboxing Safe Condition DQL AST Walker
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
use Doctrine\ORM\Query\AST; | |
use Doctrine\ORM\Query\TreeWalkerAdapter; | |
class SafeConditionWalker extends TreeWalkerAdapter | |
{ | |
/** @var bool */ | |
private $inCondition = false; | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkSelectStatement(AST\SelectStatement $selectStatement) | |
{ | |
$this->notAllowedIfInCondition('select statements are not allowed.'); | |
if ($selectStatement->whereClause) { | |
$this->walkWhereClause($selectStatement->whereClause); | |
} | |
if ($selectStatement->havingClause) { | |
$this->walkHavingClause($selectStatement->havingClause); | |
} | |
if ($selectStatement->orderByClause) { | |
$this->walkOrderByClause($selectStatement->orderByClause); | |
} | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkUpdateStatement(AST\UpdateStatement $updateStatement) | |
{ | |
$this->notAllowedIfInCondition('update statements are not allowed.'); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkDeleteStatement(AST\DeleteStatement $deleteStatement) | |
{ | |
$this->notAllowedIfInCondition('delete statements are not allowed.'); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkSelectClause($selectClause) | |
{ | |
$this->notAllowedIfInCondition('select clauses are not allowed.'); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkFromClause($fromClause) | |
{ | |
$this->notAllowedIfInCondition('from clauses are not allowed.'); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkHavingClause($havingClause) | |
{ | |
$this->walkConditionalExpression($havingClause->conditionalExpression); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkJoin($join) | |
{ | |
$this->notAllowedIfInCondition('joins are not allowed.'); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkSelectExpression($selectExpression) | |
{ | |
$this->notAllowedIfInCondition('select expression are not allowed.'); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkQuantifiedExpression($quantifiedExpression) | |
{ | |
$this->notAllowedIfInCondition('quantified expressions are not allowed.'); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkSubselect($subselect) | |
{ | |
$this->notAllowedIfInCondition('subselects are not allowed.'); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkSubselectFromClause($subselectFromClause) | |
{ | |
$this->notAllowedIfInCondition('subselect from clauses are not allowed.'); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkSimpleSelectClause($simpleSelectClause) | |
{ | |
$this->notAllowedIfInCondition('simple select clauses are not allowed.'); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkSimpleSelectExpression($simpleSelectExpression) | |
{ | |
$this->notAllowedIfInCondition('simple select expressions are not allowed.'); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkAggregateExpression($aggregateExpression) | |
{ | |
$this->walkSimpleArithmeticExpression($aggregateExpression->pathExpression); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkDeleteClause(AST\DeleteClause $deleteClause) | |
{ | |
$this->notAllowedIfInCondition('delete clauses are not allowed.'); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkUpdateClause($updateClause) | |
{ | |
$this->notAllowedIfInCondition('update clauses are not allowed.'); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkUpdateItem($updateItem) | |
{ | |
$this->notAllowedIfInCondition('update items are not allowed.'); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkWhereClause($whereClause) | |
{ | |
$this->walkConditionalExpression($whereClause->conditionalExpression); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkConditionalExpression($conditionalExpression) | |
{ | |
$this->inCondition = true; | |
if (!$conditionalExpression instanceof AST\ConditionalExpression) { | |
return $this->walkConditionalTerm($conditionalExpression); | |
} | |
array_walk($conditionalExpression->conditionalTerms, array($this, 'walkConditionalTerm')); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkConditionalTerm($conditionalTerm) | |
{ | |
if (!$conditionalTerm instanceof AST\ConditionalTerm) { | |
return $this->walkConditionalFactor($conditionalTerm); | |
} | |
array_walk($conditionalTerm->conditionalFactors, array($this, 'walkConditionalFactor')); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkConditionalFactor($factor) | |
{ | |
$this->walkConditionalPrimary($factor instanceof AST\ConditionalFactor ? $factor->conditionalPrimary : $factor); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkConditionalPrimary($primary) | |
{ | |
if ($primary->isSimpleConditionalExpression()) { | |
return $primary->simpleConditionalExpression->dispatch($this); | |
} | |
if ($primary->isConditionalExpression()) { | |
$this->walkConditionalExpression($primary->conditionalExpression); | |
} | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkExistsExpression($existsExpression) | |
{ | |
$this->notAllowedIfInCondition('exists expressions are not allowed.'); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkCollectionMemberExpression($collectionMemberExpression) | |
{ | |
if ($collectionMemberExpression->entityExpression instanceof AST\InputParameter) { | |
$this->walkInputParameter($collectionMemberExpression->entityExpression); | |
} | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkNullComparisonExpression($nullComparisonExpression) | |
{ | |
if ($nullComparisonExpression->expression instanceof AST\InputParameter) { | |
$this->walkInputParameter($nullComparisonExpression->expression); | |
} | |
$nullComparisonExpression->expression->dispatch($this); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkInExpression($inExpression) | |
{ | |
$this->walkArithmeticExpression($inExpression->expression); | |
if ($inExpression->subselect) { | |
$this->walkSubselect($inExpression->subselect); | |
} | |
array_walk($inExpression->literals, array($this, 'walkInParameter')); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkInstanceOfExpression($instanceOfExpression) | |
{ | |
$this->notAllowedIfInCondition('instanceOf expressions are not allowed.'); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkInParameter($inParameter) | |
{ | |
if ($inParameter instanceof AST\InputParameter) { | |
$this->walkInputParameter($inParameter); | |
} | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkBetweenExpression($betweenExpression) | |
{ | |
$this->walkArithmeticExpression($betweenExpression->expression); | |
$this->walkArithmeticExpression($betweenExpression->leftBetweenExpression); | |
$this->walkArithmeticExpression($betweenExpression->rightBetweenExpression); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkLikeExpression($likeExpression) | |
{ | |
$likeExpression->stringExpression->dispatch($this); | |
if ($likeExpression->stringPattern instanceof AST\InputParameter) { | |
$this->walkInputParameter($likeExpression->stringPattern); | |
} | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkComparisonExpression($comparisonExpression) | |
{ | |
if ($comparisonExpression->leftExpression instanceof AST\Node) { | |
$comparisonExpression->leftExpression->dispatch($this); | |
} | |
if ($comparisonExpression->rightExpression instanceof AST\Node) { | |
$comparisonExpression->rightExpression->dispatch($this); | |
} | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkInputParameter($inputParameter) | |
{ | |
$this->notAllowedIfInCondition('input parameters are not allowed.'); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkArithmeticExpression($arithmeticExpression) | |
{ | |
if ($arithmeticExpression->isSubselect()) { | |
$this->walkSubselect($arithmeticExpression->subselect); | |
} | |
$this->walkSimpleArithmeticExpression($arithmeticExpression->simpleArithmeticExpression); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkSimpleArithmeticExpression($simpleArithmeticExpression) | |
{ | |
if (!$simpleArithmeticExpression instanceof AST\SimpleArithmeticExpression) { | |
return $this->walkArithmeticTerm($simpleArithmeticExpression); | |
} | |
array_walk($simpleArithmeticExpression->arithmeticTerms, array($this, 'walkArithmeticTerm')); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkArithmeticTerm($arithmeticTerm) | |
{ | |
if (is_string($arithmeticTerm)) { | |
return; | |
} | |
if (!$arithmeticTerm instanceof AST\ArithmeticTerm) { | |
return $this->walkArithmeticFactor($arithmeticTerm); | |
} | |
array_walk($arithmeticTerm->arithmeticFactors, array($this, 'walkArithmeticFactor')); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkArithmeticFactor($arithmeticFactor) | |
{ | |
if (is_string($arithmeticFactor)) { | |
return; | |
} elseif (!$arithmeticFactor instanceof AST\ArithmeticFactor) { | |
return $this->walkArithmeticPrimary($arithmeticFactor); | |
} | |
$this->walkArithmeticPrimary($arithmeticFactor->arithmeticPrimary); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkArithmeticPrimary($arithmeticPrimary) | |
{ | |
if ($arithmeticPrimary instanceof AST\SimpleArithmeticExpression) { | |
$this->walkSimpleArithmeticExpression($arithmeticPrimary); | |
} elseif ($arithmeticPrimary instanceof AST\Node) { | |
$arithmeticPrimary->dispatch($this); | |
} | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function walkStringPrimary($stringPrimary) | |
{ | |
if (!is_string($stringPrimary)) { | |
$stringPrimary->dispatch($this); | |
} | |
} | |
/** | |
* @param string $message | |
* @throws \Exception | |
*/ | |
private function notAllowedIfInCondition($message) | |
{ | |
if ($this->inCondition) { | |
throw InvalidQueryException::notAllowed($message); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment