appserver-io /
doppelgaenger
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | |||
| 3 | /** |
||
| 4 | * \AppserverIo\Doppelgaenger\AspectRegister |
||
| 5 | * |
||
| 6 | * NOTICE OF LICENSE |
||
| 7 | * |
||
| 8 | * This source file is subject to the Open Software License (OSL 3.0) |
||
| 9 | * that is available through the world-wide-web at this URL: |
||
| 10 | * http://opensource.org/licenses/osl-3.0.php |
||
| 11 | * |
||
| 12 | * PHP version 5 |
||
| 13 | * |
||
| 14 | * @author Bernhard Wick <[email protected]> |
||
| 15 | * @copyright 2015 TechDivision GmbH - <[email protected]> |
||
| 16 | * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) |
||
| 17 | * @link https://github.com/appserver-io/doppelgaenger |
||
| 18 | * @link http://www.appserver.io/ |
||
| 19 | */ |
||
| 20 | |||
| 21 | namespace AppserverIo\Doppelgaenger; |
||
| 22 | |||
| 23 | use AppserverIo\Doppelgaenger\Entities\Definitions\Advice; |
||
| 24 | use AppserverIo\Doppelgaenger\Entities\Definitions\Aspect; |
||
| 25 | use AppserverIo\Doppelgaenger\Entities\Definitions\AspectDefinition; |
||
| 26 | use AppserverIo\Doppelgaenger\Entities\Lists\AbstractTypedList; |
||
| 27 | use AppserverIo\Doppelgaenger\Entities\Lists\TypedList; |
||
| 28 | use AppserverIo\Doppelgaenger\Entities\PointcutExpression; |
||
| 29 | use AppserverIo\Doppelgaenger\Entities\Pointcuts\PointcutFactory; |
||
| 30 | use AppserverIo\Doppelgaenger\Entities\Definitions\Pointcut as PointcutDefinition; |
||
| 31 | use AppserverIo\Doppelgaenger\Entities\Pointcuts\PointcutPointcut; |
||
| 32 | use AppserverIo\Psr\MetaobjectProtocol\Aop\Annotations\Advices\After; |
||
| 33 | use AppserverIo\Psr\MetaobjectProtocol\Aop\Annotations\Advices\AfterReturning; |
||
| 34 | use AppserverIo\Psr\MetaobjectProtocol\Aop\Annotations\Advices\AfterThrowing; |
||
| 35 | use AppserverIo\Psr\MetaobjectProtocol\Aop\Annotations\Advices\Around; |
||
| 36 | use AppserverIo\Psr\MetaobjectProtocol\Aop\Annotations\Advices\Before; |
||
| 37 | use AppserverIo\Psr\MetaobjectProtocol\Aop\Annotations\Pointcut; |
||
| 38 | use Herrera\Annotations\Convert\ToArray; |
||
| 39 | use Herrera\Annotations\Tokenizer; |
||
| 40 | use Herrera\Annotations\Tokens; |
||
| 41 | |||
| 42 | /** |
||
| 43 | * Class which knows about registered aspects to allow for checks of methods against all given pointcuts |
||
| 44 | * |
||
| 45 | * @author Bernhard Wick <[email protected]> |
||
| 46 | * @copyright 2015 TechDivision GmbH - <[email protected]> |
||
| 47 | * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) |
||
| 48 | * @link https://github.com/appserver-io/doppelgaenger |
||
| 49 | * @link http://www.appserver.io/ |
||
| 50 | */ |
||
| 51 | class AspectRegister extends AbstractTypedList |
||
| 52 | { |
||
| 53 | |||
| 54 | /** |
||
| 55 | * Default constructor |
||
| 56 | */ |
||
| 57 | public function __construct() |
||
| 58 | { |
||
| 59 | parent::__construct(); |
||
| 60 | |||
| 61 | $this->itemType = '\AppserverIo\Doppelgaenger\Entities\Definitions\Aspect'; |
||
| 62 | $this->defaultOffset = 'qualifiedName'; |
||
| 63 | } |
||
| 64 | |||
| 65 | /** |
||
| 66 | * Look up a certain advice based on a glob-like expression optionally containing aspect name and advice name |
||
| 67 | * |
||
| 68 | * @param string $adviceExpression Expression defining the search term |
||
| 69 | * |
||
| 70 | * @return array<\AppserverIo\Doppelgaenger\Entities\Definitions\Advice> |
||
| 71 | */ |
||
| 72 | View Code Duplication | public function lookupAdvice($adviceExpression) |
|
| 73 | { |
||
| 74 | // clean the expression |
||
| 75 | $adviceExpression = trim(ltrim(rtrim($adviceExpression, '()'), '\\')); |
||
| 76 | |||
| 77 | // if there is an aspect name within the expression we have to filter our search range and cut the expression |
||
| 78 | $container = $this->container; |
||
| 79 | if (strpos($adviceExpression, '->')) { |
||
| 80 | $aspectExpression = strstr($adviceExpression, '->', true); |
||
| 81 | $container = $this->lookupAspects($aspectExpression); |
||
| 82 | $adviceExpression = str_replace('->', '', strstr($adviceExpression, '->')); |
||
| 83 | } |
||
| 84 | |||
| 85 | $matches = array(); |
||
| 86 | foreach ($container as $aspect) { |
||
| 87 | $matches = array_merge($matches, $this->lookupEntries($aspect->getAdvices(), $adviceExpression)); |
||
| 88 | } |
||
| 89 | |||
| 90 | return $matches; |
||
| 91 | } |
||
| 92 | |||
| 93 | /** |
||
| 94 | * Will narrow down the choice of aspects to make when looking up pointcuts or advices. |
||
| 95 | * Just pass the expression to look up any of both |
||
| 96 | * |
||
| 97 | * @param string $expression Expression defining the search term |
||
| 98 | * |
||
| 99 | * @return array<\AppserverIo\Doppelgaenger\Entities\Definitions\Aspect> |
||
| 100 | */ |
||
| 101 | public function lookupAspects($expression) |
||
| 102 | { |
||
| 103 | return $this->lookupEntries($this->container, $expression); |
||
| 104 | } |
||
| 105 | |||
| 106 | /** |
||
| 107 | * Look up certain entities in a container based on their qualified name and a glob-like expression |
||
| 108 | * |
||
| 109 | * @param array|\Traversable $container Traversable container we will look in |
||
| 110 | * @param string $expression Expression defining the search term |
||
| 111 | * |
||
| 112 | * @return array |
||
| 113 | */ |
||
| 114 | protected function lookupEntries($container, $expression) |
||
| 115 | { |
||
| 116 | |||
| 117 | // clean the expression |
||
| 118 | $expression = trim(ltrim(rtrim($expression, '()'), '\\')); |
||
| 119 | |||
| 120 | // if we got the complete name of the aspect we can return it alone |
||
| 121 | if ($this->entryExists($expression)) { |
||
| 122 | return array($this->get($expression)); |
||
| 123 | } |
||
| 124 | |||
| 125 | // as it seems we got something else we have to get all regex about |
||
| 126 | $matches = array(); |
||
| 127 | foreach ($container as $entry) { |
||
| 128 | if (fnmatch($expression, $entry->getQualifiedName())) { |
||
| 129 | $matches[] = $entry; |
||
| 130 | } |
||
| 131 | } |
||
| 132 | |||
| 133 | return $matches; |
||
| 134 | } |
||
| 135 | |||
| 136 | /** |
||
| 137 | * Look up a certain advice based on a glob-like expression optionally containing aspect name and pointcut name |
||
| 138 | * |
||
| 139 | * @param string $pointcutExpression Expression defining the search term |
||
| 140 | * |
||
| 141 | * @return array<\AppserverIo\Doppelgaenger\Entities\Definitions\Pointcut> |
||
| 142 | */ |
||
| 143 | View Code Duplication | public function lookupPointcuts($pointcutExpression) |
|
| 144 | { |
||
| 145 | // clean the expression |
||
| 146 | $pointcutExpression = trim(ltrim(rtrim($pointcutExpression, '()'), '\\')); |
||
| 147 | |||
| 148 | // if there is an aspect name within the expression we have to filter our search range and cut the expression |
||
| 149 | $container = $this->container; |
||
| 150 | if (strpos($pointcutExpression, '->')) { |
||
| 151 | $aspectExpression = strstr($pointcutExpression, '->', true); |
||
| 152 | $container = $this->lookupAspects($aspectExpression); |
||
| 153 | $pointcutExpression = str_replace('->', '', strstr($pointcutExpression, '->')); |
||
| 154 | } |
||
| 155 | |||
| 156 | $matches = array(); |
||
| 157 | foreach ($container as $aspect) { |
||
| 158 | $matches = array_merge($matches, $this->lookupEntries($aspect->getPointcuts(), $pointcutExpression)); |
||
| 159 | } |
||
| 160 | |||
| 161 | return $matches; |
||
| 162 | } |
||
| 163 | |||
| 164 | /** |
||
| 165 | * Will register a complete aspect to the AspectRegister. |
||
| 166 | * This include its advices and pointcuts which can be looked up from this point on |
||
| 167 | * |
||
| 168 | * @param \AppserverIo\Doppelgaenger\Entities\Definitions\AspectDefinition $aspectDefinition Structure to register as an aspect |
||
| 169 | * |
||
| 170 | * @return null |
||
| 171 | */ |
||
| 172 | public function register(AspectDefinition $aspectDefinition) |
||
| 173 | { |
||
| 174 | |||
| 175 | // create the new aspect and fill it with things we already know |
||
| 176 | $aspect = new Aspect(); |
||
| 177 | $aspect->setName($aspectDefinition->getName()); |
||
| 178 | $aspect->setNamespace($aspectDefinition->getNamespace()); |
||
| 179 | |||
| 180 | // prepare the tokenizer we will need for further processing |
||
| 181 | $needles = array( |
||
| 182 | AfterReturning::ANNOTATION, |
||
| 183 | AfterThrowing::ANNOTATION, |
||
| 184 | After::ANNOTATION, |
||
| 185 | Around::ANNOTATION, |
||
| 186 | Before::ANNOTATION |
||
| 187 | ); |
||
| 188 | $tokenizer = new Tokenizer(); |
||
| 189 | $tokenizer->ignore( |
||
| 190 | array( |
||
| 191 | 'param', |
||
| 192 | 'return', |
||
| 193 | 'throws' |
||
| 194 | ) |
||
| 195 | ); |
||
| 196 | |||
| 197 | // iterate the functions and filter out the ones used as advices |
||
| 198 | $scheduledAdviceDefinitions = array(); |
||
| 199 | foreach ($aspectDefinition->getFunctionDefinitions() as $functionDefinition) { |
||
|
0 ignored issues
–
show
|
|||
| 200 | $foundNeedle = false; |
||
| 201 | foreach ($needles as $needle) { |
||
| 202 | // create the advice |
||
| 203 | if (strpos($functionDefinition->getDocBlock(), '@' . $needle) !== false) { |
||
| 204 | $foundNeedle = true; |
||
| 205 | $scheduledAdviceDefinitions[$needle][] = $functionDefinition; |
||
| 206 | |||
| 207 | break; |
||
| 208 | } |
||
| 209 | } |
||
| 210 | |||
| 211 | // create the pointcut |
||
| 212 | if (!$foundNeedle && strpos($functionDefinition->getDocBlock(), '@' . Pointcut::ANNOTATION) !== false) { |
||
| 213 | $pointcut = new PointcutDefinition(); |
||
| 214 | $pointcut->setName($functionDefinition->getName()); |
||
| 215 | |||
| 216 | $tokens = new Tokens($tokenizer->parse($functionDefinition->getDocBlock())); |
||
| 217 | |||
| 218 | // convert to array and run it through our advice factory |
||
| 219 | $toArray = new ToArray(); |
||
| 220 | $annotations = $toArray->convert($tokens); |
||
| 221 | |||
| 222 | // create the entities for the join-points and advices the pointcut describes |
||
| 223 | $pointcut->setPointcutExpression(new PointcutExpression(array_pop(array_pop($annotations)->values))); |
||
| 224 | $aspect->getPointcuts()->add($pointcut); |
||
| 225 | } |
||
| 226 | } |
||
| 227 | $this->add($aspect); |
||
| 228 | |||
| 229 | // do the pointcut lookups where we will need the pointcut factory for later use |
||
| 230 | $pointcutFactory = new PointcutFactory(); |
||
| 231 | foreach ($scheduledAdviceDefinitions as $codeHook => $hookedAdviceDefinitions) { |
||
| 232 | foreach ($hookedAdviceDefinitions as $scheduledAdviceDefinition) { |
||
| 233 | // create our advice |
||
| 234 | $advice = new Advice(); |
||
| 235 | $advice->setAspectName($aspectDefinition->getQualifiedName()); |
||
| 236 | $advice->setName($scheduledAdviceDefinition->getName()); |
||
| 237 | $advice->setCodeHook((string) $codeHook); |
||
| 238 | |||
| 239 | $tokens = new Tokens($tokenizer->parse($scheduledAdviceDefinition->getDocBlock())); |
||
| 240 | |||
| 241 | // convert to array and run it through our advice factory |
||
| 242 | $toArray = new ToArray(); |
||
| 243 | $annotations = $toArray->convert($tokens); |
||
| 244 | |||
| 245 | // create the entities for the join-points and advices the pointcut describes |
||
| 246 | foreach ($annotations as $annotation) { |
||
| 247 | $pointcut = $pointcutFactory->getInstance(array_pop($annotation->values)); |
||
| 248 | if ($pointcut instanceof PointcutPointcut) { |
||
| 249 | // get the referenced pointcuts for the split parts of the expression |
||
| 250 | $expressionParts = explode(PointcutPointcut::EXPRESSION_CONNECTOR, $pointcut->getExpression()); |
||
| 251 | |||
| 252 | // lookup all the referenced pointcuts |
||
| 253 | $referencedPointcuts = array(); |
||
| 254 | foreach ($expressionParts as $expressionPart) { |
||
| 255 | $referencedPointcuts = array_merge($referencedPointcuts, $this->lookupPointcuts($expressionPart)); |
||
| 256 | } |
||
| 257 | |||
| 258 | $pointcut->setReferencedPointcuts($referencedPointcuts); |
||
| 259 | } |
||
| 260 | |||
| 261 | $advice->getPointcuts()->add($pointcut); |
||
| 262 | } |
||
| 263 | |||
| 264 | $aspect->getAdvices()->add($advice); |
||
| 265 | } |
||
| 266 | } |
||
| 267 | |||
| 268 | $this->set($aspectDefinition->getQualifiedName(), $aspect); |
||
| 269 | } |
||
| 270 | } |
||
| 271 |
There are different options of fixing this problem.
If you want to be on the safe side, you can add an additional type-check:
If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:
Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.