/** * @param string $indexName * @param string $indexType Class name for index instance * @return \Flowpack\SimpleSearch\Domain\Service\IndexInterface * @throws \Flowpack\SimpleSearch\Exception */ public function create($indexName, $indexType = NULL) { if (!isset($indexType)) { if ($this->objectManager === NULL) { throw new \Flowpack\SimpleSearch\Exception('If this package is used outside of a TYPO3 Flow context you must specify the $indexType argument.', 1398018955); } $indexType = $this->objectManager->getClassNameByObjectName('Flowpack\\SimpleSearch\\Domain\\Service\\IndexInterface'); } $instanceIdentifier = md5($indexName . '#' . $indexType); if (!isset($this->searchIndexInstances[$instanceIdentifier])) { $this->searchIndexInstances[$instanceIdentifier] = new $indexType($indexName); } return $this->searchIndexInstances[$instanceIdentifier]; }
/** * Matches a \TYPO3\Flow\Mvc\RequestInterface against the configured CSRF pattern rules and * searches for invalid csrf tokens. If this returns TRUE, the request is invalid! * * @param RequestInterface $request The request that should be matched * @return boolean TRUE if the pattern matched, FALSE otherwise * @throws AuthenticationRequiredException */ public function matchRequest(RequestInterface $request) { if (!$request instanceof ActionRequest || $request->getHttpRequest()->isMethodSafe()) { $this->systemLogger->log('CSRF: No token required, safe request', LOG_DEBUG); return false; } if ($this->authenticationManager->isAuthenticated() === false) { $this->systemLogger->log('CSRF: No token required, not authenticated', LOG_DEBUG); return false; } if ($this->securityContext->areAuthorizationChecksDisabled() === true) { $this->systemLogger->log('CSRF: No token required, authorization checks are disabled', LOG_DEBUG); return false; } $controllerClassName = $this->objectManager->getClassNameByObjectName($request->getControllerObjectName()); $actionMethodName = $request->getControllerActionName() . 'Action'; if (!$this->hasPolicyEntryForMethod($controllerClassName, $actionMethodName)) { $this->systemLogger->log(sprintf('CSRF: No token required, method %s::%s() is not restricted by a policy.', $controllerClassName, $actionMethodName), LOG_DEBUG); return false; } if ($this->reflectionService->isMethodTaggedWith($controllerClassName, $actionMethodName, 'skipcsrfprotection')) { $this->systemLogger->log(sprintf('CSRF: No token required, method %s::%s() is tagged with a "skipcsrfprotection" annotation', $controllerClassName, $actionMethodName), LOG_DEBUG); return false; } $httpRequest = $request->getHttpRequest(); if ($httpRequest->hasHeader('X-Flow-Csrftoken')) { $csrfToken = $httpRequest->getHeader('X-Flow-Csrftoken'); } else { $internalArguments = $request->getMainRequest()->getInternalArguments(); $csrfToken = isset($internalArguments['__csrfToken']) ? $internalArguments['__csrfToken'] : null; } if (empty($csrfToken)) { $this->systemLogger->log(sprintf('CSRF: token was empty but a valid token is required for %s::%s()', $controllerClassName, $actionMethodName), LOG_DEBUG); return true; } if (!$this->securityContext->hasCsrfProtectionTokens()) { throw new AuthenticationRequiredException(sprintf('CSRF: No CSRF tokens in security context, possible session timeout. A valid token is required for %s::%s()', $controllerClassName, $actionMethodName), 1317309673); } if ($this->securityContext->isCsrfProtectionTokenValid($csrfToken) === false) { $this->systemLogger->log(sprintf('CSRF: token was invalid but a valid token is required for %s::%s()', $controllerClassName, $actionMethodName), LOG_DEBUG); return true; } $this->systemLogger->log(sprintf('CSRF: Successfully verified token for %s::%s()', $controllerClassName, $actionMethodName), LOG_DEBUG); return false; }
/** * Creates a node from the given NodeData container. * * If this factory has previously created a Node for the given $node and it's dimensions, * it will return the same node again. * * @param NodeData $nodeData * @param Context $context * @return \TYPO3\TYPO3CR\Domain\Model\NodeInterface * @throws \TYPO3\TYPO3CR\Exception\NodeConfigurationException if a configured 'class' for a Node does not exist or does not inherit NodeInterface */ public function createFromNodeData(NodeData $nodeData, Context $context) { if ($nodeData->isInternal()) { return null; } $internalNodeIdentifier = $nodeData->getIdentifier() . spl_object_hash($context); // In case there is a Node with an internal NodeData (because the NodeData was changed in the meantime) we need to flush it. if (isset($this->nodes[$internalNodeIdentifier]) && $this->nodes[$internalNodeIdentifier]->getNodeData()->isInternal()) { unset($this->nodes[$internalNodeIdentifier]); } if (!isset($this->nodes[$internalNodeIdentifier])) { // Warning: Alternative node implementations are considered internal for now, feature can change or be removed anytime. We want to be sure it works well and makes sense before declaring it public. $class = $nodeData->getNodeType()->getConfiguration('class') ?: $this->objectManager->getClassNameByObjectName('TYPO3\\TYPO3CR\\Domain\\Model\\NodeInterface'); if (!in_array($class, static::getNodeInterfaceImplementations($this->objectManager))) { throw new NodeConfigurationException('The configured implementation class name "' . $class . '" for NodeType "' . $nodeData->getNodeType() . '" does not inherit from TYPO3\\TYPO3CR\\Domain\\Model\\NodeInterface.', 1406884014); } $this->nodes[$internalNodeIdentifier] = new $class($nodeData, $context); } $node = $this->nodes[$internalNodeIdentifier]; return $this->filterNodeByContext($node, $context); }
/** * Returns the name of the action the controller is supposed to execute. * * @return string Action name * @api */ public function getControllerActionName() { $controllerObjectName = $this->getControllerObjectName(); if ($controllerObjectName !== '' && $this->controllerActionName === strtolower($this->controllerActionName)) { $controllerClassName = $this->objectManager->getClassNameByObjectName($controllerObjectName); $lowercaseActionMethodName = strtolower($this->controllerActionName) . 'action'; foreach (get_class_methods($controllerClassName) as $existingMethodName) { if (strtolower($existingMethodName) === $lowercaseActionMethodName) { $this->controllerActionName = substr($existingMethodName, 0, -6); break; } } } return $this->controllerActionName; }
/** * Matches a \TYPO3\Flow\Mvc\RequestInterface against the configured CSRF pattern rules and * searches for invalid csrf tokens. If this returns TRUE, the request is invalid! * * @param \TYPO3\Flow\Mvc\RequestInterface $request The request that should be matched * @return boolean TRUE if the pattern matched, FALSE otherwise * @throws \TYPO3\Flow\Security\Exception\AuthenticationRequiredException */ public function matchRequest(\TYPO3\Flow\Mvc\RequestInterface $request) { if (!$request instanceof ActionRequest || $request->getHttpRequest()->isMethodSafe()) { $this->systemLogger->log('No CSRF required, safe request', LOG_DEBUG); return FALSE; } if ($this->authenticationManager->isAuthenticated() === FALSE) { $this->systemLogger->log('No CSRF required, not authenticated', LOG_DEBUG); return FALSE; } if ($this->securityContext->areAuthorizationChecksDisabled() === TRUE) { $this->systemLogger->log('No CSRF required, authorization checks are disabled', LOG_DEBUG); return FALSE; } $controllerClassName = $this->objectManager->getClassNameByObjectName($request->getControllerObjectName()); $actionName = $request->getControllerActionName() . 'Action'; if (!$this->policyService->hasPolicyEntryForMethod($controllerClassName, $actionName)) { $this->systemLogger->log(sprintf('CSRF protection filter: allowed %s request without requiring CSRF token because action "%s" in controller "%s" is not restricted by a policy.', $request->getHttpRequest()->getMethod(), $actionName, $controllerClassName), LOG_NOTICE); return FALSE; } if ($this->reflectionService->isMethodTaggedWith($controllerClassName, $actionName, 'skipcsrfprotection')) { return FALSE; } $httpRequest = $request->getHttpRequest(); if ($httpRequest->hasHeader('X-Flow-Csrftoken')) { $csrfToken = $httpRequest->getHeader('X-Flow-Csrftoken'); } else { $internalArguments = $request->getMainRequest()->getInternalArguments(); $csrfToken = isset($internalArguments['__csrfToken']) ? $internalArguments['__csrfToken'] : NULL; } if (empty($csrfToken)) { $this->systemLogger->log('CSRF token was empty', LOG_DEBUG); return TRUE; } if (!$this->securityContext->hasCsrfProtectionTokens()) { throw new \TYPO3\Flow\Security\Exception\AuthenticationRequiredException('No tokens in security context, possible session timeout', 1317309673); } if ($this->securityContext->isCsrfProtectionTokenValid($csrfToken) === FALSE) { $this->systemLogger->log('CSRF token was invalid', LOG_DEBUG); return TRUE; } // the CSRF token was necessary and is valid return FALSE; }
/** * Reconstitutes an object from a serialized object without calling the constructor. * * @param string $objectHash Identifier of the serialized object * @param array $objectData The object data array * @return object */ protected function reconstituteObject($objectHash, array $objectData) { if (isset($this->reconstitutedObjects[$objectHash])) { return $this->reconstitutedObjects[$objectHash]; } $className = $this->objectManager->getClassNameByObjectName($objectData[self::CLASSNAME]); $object = unserialize('O:' . strlen($className) . ':"' . $className . '":0:{};'); $this->reconstitutedObjects[$objectHash] = $object; foreach ($objectData[self::PROPERTIES] as $propertyName => $propertyData) { switch ($propertyData[self::TYPE]) { case 'simple': $propertyValue = $propertyData[self::VALUE]; break; case 'array': $propertyValue = $this->reconstituteArray($propertyData[self::VALUE]); break; case 'Collection': $propertyValue = $this->reconstituteCollection($propertyData[self::CLASSNAME], $propertyData[self::VALUE]); break; case 'ArrayObject': $propertyValue = new \ArrayObject($this->reconstituteArray($propertyData[self::VALUE])); break; case 'object': $propertyValue = $this->reconstituteObject($propertyData[self::VALUE], $this->objectsAsArray[$propertyData[self::VALUE]]); break; case 'SplObjectStorage': $propertyValue = $this->reconstituteSplObjectStorage($propertyData[self::VALUE]); break; case 'persistenceObject': list($propertyClassName, $propertyUuid) = explode(':', $propertyData[self::VALUE]); $propertyValue = $this->reconstitutePersistenceObject($propertyClassName, $propertyUuid); break; } $reflectionProperty = new \ReflectionProperty(get_class($object), $propertyName); $reflectionProperty->setAccessible(true); $reflectionProperty->setValue($object, $propertyValue); } return $object; }
/** * Builds a new instance of $objectType with the given $possibleConstructorArgumentValues. * If constructor argument values are missing from the given array the method looks for a * default value in the constructor signature. * * Furthermore, the constructor arguments are removed from $possibleConstructorArgumentValues * * @param array &$possibleConstructorArgumentValues * @param string $objectType * @return object The created instance * @throws InvalidTargetException if a required constructor argument is missing */ protected function buildObject(array &$possibleConstructorArgumentValues, $objectType) { $constructorArguments = array(); $className = $this->objectManager->getClassNameByObjectName($objectType); $constructorSignature = $this->getConstructorArgumentsForClass($className); if (count($constructorSignature)) { foreach ($constructorSignature as $constructorArgumentName => $constructorArgumentReflection) { if (array_key_exists($constructorArgumentName, $possibleConstructorArgumentValues)) { $constructorArguments[] = $possibleConstructorArgumentValues[$constructorArgumentName]; unset($possibleConstructorArgumentValues[$constructorArgumentName]); } elseif ($constructorArgumentReflection['optional'] === TRUE) { $constructorArguments[] = $constructorArgumentReflection['defaultValue']; } else { throw new InvalidTargetException('Missing constructor argument "' . $constructorArgumentName . '" for object of type "' . $objectType . '".', 1268734872); } } $classReflection = new \ReflectionClass($className); return $classReflection->newInstanceArgs($constructorArguments); } else { return new $className(); } }
/** * Builds a new instance of $objectType with the given $possibleConstructorArgumentValues. * If constructor argument values are missing from the given array the method looks for a * default value in the constructor signature. * * Furthermore, the constructor arguments are removed from $possibleConstructorArgumentValues * * @param array &$possibleConstructorArgumentValues * @param string $objectType * @return object The created instance * @throws \TYPO3\Flow\Property\Exception\InvalidTargetException if a required constructor argument is missing */ protected function buildObject(array &$possibleConstructorArgumentValues, $objectType) { $className = $this->objectManager->getClassNameByObjectName($objectType); if ($this->reflectionService->hasMethod($className, '__construct')) { $constructorSignature = $this->reflectionService->getMethodParameters($className, '__construct'); $constructorArguments = array(); foreach ($constructorSignature as $constructorArgumentName => $constructorArgumentInformation) { if (array_key_exists($constructorArgumentName, $possibleConstructorArgumentValues)) { $constructorArguments[] = $possibleConstructorArgumentValues[$constructorArgumentName]; unset($possibleConstructorArgumentValues[$constructorArgumentName]); } elseif ($constructorArgumentInformation['optional'] === TRUE) { $constructorArguments[] = $constructorArgumentInformation['defaultValue']; } else { throw new \TYPO3\Flow\Property\Exception\InvalidTargetException('Missing constructor argument "' . $constructorArgumentName . '" for object of type "' . $objectType . '".', 1268734872); } } $classReflection = new \ReflectionClass($className); return $classReflection->newInstanceArgs($constructorArguments); } else { return new $className(); } }
/** * Dispatches a signal by calling the registered Slot methods * * @param string $signalClassName Name of the class containing the signal * @param string $signalName Name of the signal * @param array $signalArguments arguments passed to the signal method * @return void * @throws \TYPO3\Flow\SignalSlot\Exception\InvalidSlotException if the slot is not valid * @api */ public function dispatch($signalClassName, $signalName, array $signalArguments = array()) { if (!isset($this->slots[$signalClassName][$signalName])) { return; } foreach ($this->slots[$signalClassName][$signalName] as $slotInformation) { if (isset($slotInformation['object'])) { $object = $slotInformation['object']; } elseif (substr($slotInformation['method'], 0, 2) === '::') { if (!isset($this->objectManager)) { if (is_callable($slotInformation['class'] . $slotInformation['method'])) { $object = $slotInformation['class']; } else { throw new \TYPO3\Flow\SignalSlot\Exception\InvalidSlotException(sprintf('Cannot dispatch %s::%s to class %s. The object manager is not yet available in the Signal Slot Dispatcher and therefore it cannot dispatch classes.', $signalClassName, $signalName, $slotInformation['class']), 1298113624); } } else { $object = $this->objectManager->getClassNameByObjectName($slotInformation['class']); } $slotInformation['method'] = substr($slotInformation['method'], 2); } else { if (!isset($this->objectManager)) { throw new \TYPO3\Flow\SignalSlot\Exception\InvalidSlotException(sprintf('Cannot dispatch %s::%s to class %s. The object manager is not yet available in the Signal Slot Dispatcher and therefore it cannot dispatch classes.', $signalClassName, $signalName, $slotInformation['class']), 1298113624); } if (!$this->objectManager->isRegistered($slotInformation['class'])) { throw new \TYPO3\Flow\SignalSlot\Exception\InvalidSlotException('The given class "' . $slotInformation['class'] . '" is not a registered object.', 1245673367); } $object = $this->objectManager->get($slotInformation['class']); } if ($slotInformation['passSignalInformation'] === TRUE) { $signalArguments[] = $signalClassName . '::' . $signalName; } if (!method_exists($object, $slotInformation['method'])) { throw new \TYPO3\Flow\SignalSlot\Exception\InvalidSlotException('The slot method ' . get_class($object) . '->' . $slotInformation['method'] . '() does not exist.', 1245673368); } call_user_func_array(array($object, $slotInformation['method']), $signalArguments); } }