/** * @return NodeInterface */ public function getCurrentUserNode() { try { return $this->profileService->getCurrentPartyProfile(); } catch (\Exception $exception) { $this->systemLogger->log('Profile node could not be fetched: ' . $exception->getMessage(), LOG_CRIT); } }
/** * Checks the cache for the route path given in the Request and returns the result * * @param Request $httpRequest * @return array|boolean the cached route values or FALSE if no cache entry was found */ public function getCachedMatchResults(Request $httpRequest) { $cachedResult = $this->routeCache->get($this->buildRouteCacheIdentifier($httpRequest)); if ($cachedResult !== FALSE) { $this->systemLogger->log(sprintf('Router route(): A cached Route with the cache identifier "%s" matched the path "%s".', $this->buildRouteCacheIdentifier($httpRequest), $httpRequest->getRelativePath()), LOG_DEBUG); } return $cachedResult; }
private function processReceiverGroup(ReceiverGroup $receiverGroup, $language = NULL) { $cacheFileName = $receiverGroup->getCacheFileName($language); $jqProcess = escapeshellarg('cat ' . escapeshellcmd($receiverGroup->getReceiverSource()->getSourceFileName()) . ' | jq -c ' . escapeshellarg($this->convertFilterIntoJqExpression($receiverGroup->getFilter($language))) . ' > ' . escapeshellcmd($cacheFileName) . ' ; wc -l < ' . escapeshellcmd($cacheFileName) . ' > ' . escapeshellcmd($cacheFileName . '.lines')); $finalProcess = 'nohup /bin/bash -c ' . $jqProcess . ' &'; $this->systemLogger->log('Starting process: ' . $finalProcess); $proc = new Process($finalProcess); $proc->start(); }
/** * Before advice for all methods annotated with "@Flow\Session(autoStart=true)". * Those methods will trigger a session initialization if a session does not exist * yet. * * @param \TYPO3\Flow\Aop\JoinPointInterface $joinPoint The current join point * @return void * @fixme The pointcut expression below does not consider the options of the session annotation – needs adjustments in the AOP framework * @Flow\Before("methodAnnotatedWith(TYPO3\Flow\Annotations\Session)") */ public function initializeSession(\TYPO3\Flow\Aop\JoinPointInterface $joinPoint) { if ($this->session->isStarted() === TRUE) { return; } $objectName = $this->objectManager->getObjectNameByClassName(get_class($joinPoint->getProxy())); $methodName = $joinPoint->getMethodName(); $this->systemLogger->log(sprintf('Session initialization triggered by %s->%s.', $objectName, $methodName), LOG_DEBUG); $this->session->start(); }
/** * Flush caches according to the previously registered node changes. * * @return void */ public function shutdownObject() { if ($this->tagsToFlush !== array()) { foreach ($this->tagsToFlush as $tag => $logMessage) { $affectedEntries = $this->contentCache->flushByTag($tag); if ($affectedEntries > 0) { $this->systemLogger->log(sprintf('Content cache: Removed %s entries %s', $affectedEntries, $logMessage), LOG_DEBUG); } } } }
/** * @param string $event * @param string $person * * @return void */ public function removeAttendeeAction($event, $person = '') { try { $context = $this->contextFactory->create([]); $person = $this->getPersonProfile($person, $context); $event = $context->getNodeByIdentifier($event); $this->eventService->removeAttendeeFromEvent($event, $person); } catch (\Exception $exception) { $this->systemLogger->log($exception->getMessage(), LOG_ALERT); } $this->addFlashMessage('Je bent afgemeld'); $this->redirectToUri('/agenda'); }
/** * @return void */ public function pingAction() { $this->systemLogger->log("FOO" . $this->apiKey); $apiKey = $this->request->getHttpRequest()->getHeader('X-Api-Key'); $this->systemLogger->log($apiKey); if ($apiKey === $this->apiKey) { $this->response->setStatus(204); $this->response->send(); } else { $this->response->setStatus(403, 'Invalid Authentication'); $this->response->send(); } return false; }
/** * @param string $value * @throws Exception * @throws \TYPO3\Flow\Resource\Exception * @throws \TYPO3\Flow\Utility\Exception */ protected function initializeValue($value) { if (!is_array($value)) { throw new Exception('Value must be an array, with source URI (sourceUri) and filename (filename)', 1425981082); } if (!isset($value['sourceUri'])) { throw new Exception('Missing source URI', 1425981083); } $sourceUri = trim($value['sourceUri']); if (!isset($value['filename'])) { throw new Exception('Missing filename URI', 1425981084); } $filename = trim($value['filename']); $overrideFilename = isset($value['overrideFilename']) ? trim($value['overrideFilename']) : $filename; if (!isset($this->options['downloadDirectory'])) { throw new Exception('Missing download directory data type option', 1425981085); } Files::createDirectoryRecursively($this->options['downloadDirectory']); $temporaryFileAndPathname = trim($this->options['downloadDirectory'] . $filename); $this->download($sourceUri, $temporaryFileAndPathname); $sha1Hash = sha1_file($temporaryFileAndPathname); # Try to add file extenstion if missing if (!$this->downloadCache->has($sha1Hash)) { $fileExtension = pathinfo($temporaryFileAndPathname, PATHINFO_EXTENSION); if (trim($fileExtension) === '') { $mimeTypeGuesser = new MimeTypeGuesser(); $mimeType = $mimeTypeGuesser->guess($temporaryFileAndPathname); $this->logger->log(sprintf('Try to guess mime type for "%s" (%s), result: %s', $sourceUri, $filename, $mimeType), LOG_DEBUG); $fileExtension = MediaTypes::getFilenameExtensionFromMediaType($mimeType); if ($fileExtension !== '') { $oldTemporaryDestination = $temporaryFileAndPathname; $temporaryDestination = $temporaryFileAndPathname . '.' . $fileExtension; copy($oldTemporaryDestination, $temporaryDestination); $this->logger->log(sprintf('Rename "%s" to "%s"', $oldTemporaryDestination, $temporaryDestination), LOG_DEBUG); } } } $resource = $this->resourceManager->getResourceBySha1($sha1Hash); if ($resource === NULL) { $resource = $this->resourceManager->importResource($temporaryFileAndPathname); if ($filename !== $overrideFilename) { $resource->setFilename($overrideFilename); } } $this->temporaryFileAndPathname = $temporaryFileAndPathname; $this->downloadCache->set($sha1Hash, ['sha1Hash' => $sha1Hash, 'filename' => $filename, 'sourceUri' => $sourceUri, 'temporaryFileAndPathname' => $temporaryFileAndPathname]); $this->value = $resource; }
/** * Log a deprecation message once * * @return void */ protected function logDeprecation() { if (!static::$loggedDeprecation) { static::$loggedDeprecation = true; $this->logger->log('TYPO3.Media is configured to simulate the deprecated Neos 1.2 behaviour. Please check the setting "TYPO3.Media.behaviourFlag".', LOG_DEBUG); } }
/** * Renumbers the indexes of all nodes directly below the node specified by the * given path. * * Note that renumbering must happen in-memory and can't be optimized by a clever * query executed directly by the database because sorting indexes of new or * modified nodes need to be considered. * * @param string $parentPath Path to the parent node * @return void * @throws Exception\NodeException */ protected function renumberIndexesInLevel($parentPath) { $this->systemLogger->log(sprintf('Renumbering nodes in level below %s.', $parentPath), LOG_INFO); /** @var \Doctrine\ORM\Query $query */ $query = $this->entityManager->createQuery('SELECT n FROM TYPO3\\TYPO3CR\\Domain\\Model\\NodeData n WHERE n.parentPathHash = :parentPathHash ORDER BY n.index ASC'); $query->setParameter('parentPathHash', md5($parentPath)); $nodesOnLevel = array(); /** @var $node NodeData */ foreach ($query->getResult() as $node) { $nodesOnLevel[$node->getIndex()] = $node; } /** @var $node NodeData */ foreach ($this->addedNodes as $node) { if ($node->getParentPath() === $parentPath) { $index = $node->getIndex(); if (isset($nodesOnLevel[$index])) { throw new Exception\NodeException(sprintf('Index conflict for nodes %s and %s: both have index %s', $nodesOnLevel[$index]->getPath(), $node->getPath(), $index), 1317140401); } $nodesOnLevel[$index] = $node; } } // We need to sort the nodes now, to take unpersisted node orderings into account. // This fixes bug #34291 ksort($nodesOnLevel); $newIndex = 100; foreach ($nodesOnLevel as $node) { if ($newIndex > self::INDEX_MAXIMUM) { throw new Exception\NodeException(sprintf('Reached maximum node index of %s while setting index of node %s.', $newIndex, $node->getPath()), 1317140402); } $node->setIndex($newIndex); $newIndex += 100; } }
/** * @param array $nodes */ public function assignNodes(array $nodes) { $data = array(); foreach ($nodes as $node) { if ($node->getPath() !== '/') { $q = new FlowQuery(array($node)); $closestDocumentNode = $q->closest('[instanceof TYPO3.Neos:Document]')->get(0); if ($closestDocumentNode !== NULL) { $data[] = array('nodeContextPath' => $node->getContextPath(), 'documentNodeContextPath' => $closestDocumentNode->getContextPath()); } else { $this->systemLogger->log('You have a node that is no longer connected to a parent. Path: ' . $node->getPath() . ' (Identifier: ' . $node->getIdentifier() . ')'); } } } $this->assign('value', array('data' => $data, 'success' => TRUE)); }
/** * @Flow\Around("setting(Ttree.Embedly.logApiRequest) && within(Ttree\Embedly\Embedly) && method(public .*->(oembed|preview|objectify|extract|services)())") * @param JoinPointInterface $joinPoint The current join point * @return mixed */ public function getResponseFromCache(JoinPointInterface $joinPoint) { $proxy = $joinPoint->getProxy(); $key = ObjectAccess::getProperty($proxy, 'key'); $params = $joinPoint->getMethodArgument('params'); $cacheKey = md5($joinPoint->getClassName() . $joinPoint->getMethodName() . $key . json_encode($params)); if ($this->responseCache->has($cacheKey)) { $this->systemLogger->log(sprintf(' cache hit Embedly::%s', $joinPoint->getMethodName()), LOG_DEBUG); return $this->responseCache->get($cacheKey); } else { $this->systemLogger->log(sprintf(' cache miss Embedly::%s', $joinPoint->getMethodName()), LOG_DEBUG); } $response = $joinPoint->getAdviceChain()->proceed($joinPoint); $this->responseCache->set($cacheKey, $response); return $response; }
/** * Defines template if configured for provider. * * @param string $providerName * * @return bool TRUE if some configuration found, FALSE if no configuration defined for given provider. */ private function definePrettyPreRedirectTemplate($providerName) { $prettyPreRedirectPage = $this->configurationManager->getConfiguration(\TYPO3\Flow\Configuration\ConfigurationManager::CONFIGURATION_TYPE_SETTINGS, 'TYPO3.Flow.security.authentication.providers.' . $providerName . '.providerOptions.Miscellaneous.prettyPreRedirectPage'); if (empty($prettyPreRedirectPage)) { return false; } $log = ''; if (isset($prettyPreRedirectPage['layoutRootPath']) && method_exists($this->view, 'setLayoutRootPath')) { $this->view->setLayoutRootPath($prettyPreRedirectPage['layoutRootPath']); } elseif (isset($prettyPreRedirectPage['layoutRootPath']) && !method_exists($this->view, 'setLayoutRootPath')) { $log .= sprintf('Pretty pre redirect page for "%s" provider can not be used, because you use custom teplating engine and this does not know method setLayoutRootPath().', $providerName); } if (isset($prettyPreRedirectPage['partialRootPath']) && method_exists($this->view, 'setPartialRootPath')) { $this->view->setPartialRootPath($prettyPreRedirectPage['partialRootPath']); } elseif (isset($prettyPreRedirectPage['partialRootPath']) && !method_exists($this->view, 'setPartialRootPath')) { $log .= sprintf('Pretty pre redirect page for "%s" provider can not be used, because you use custom teplating engine and this does not know method setPartialRootPath().', $providerName); } if (isset($prettyPreRedirectPage['templatePathAndFilename']) && method_exists($this->view, 'setTemplatePathAndFilename')) { $this->view->setTemplatePathAndFilename($prettyPreRedirectPage['templatePathAndFilename']); } elseif (isset($prettyPreRedirectPage['templatePathAndFilename']) && !method_exists($this->view, 'setTemplatePathAndFilename')) { $log .= sprintf('Pretty pre redirect page for "%s" provider can not be used, because you use custom teplating engine and this does not know method setTemplatePathAndFilename().', $providerName); } if (!empty($log)) { $this->systemLogger->log($log, LOG_ERR); } $this->view->assignMultiple($prettyPreRedirectPage); return true; }
/** * Filters the classnames available for object management by filter expressions that either include or exclude classes. * * @param array $classNames All classnames per package * @param array $filterConfiguration The filter configuration to apply * @param string $includeOrExclude if this is an "include" or "exclude" filter * @return array the remaining class * @throws \TYPO3\Flow\Configuration\Exception\InvalidConfigurationTypeException */ protected function applyClassFilterConfiguration($classNames, $filterConfiguration, $includeOrExclude = 'include') { if (!in_array($includeOrExclude, array('include', 'exclude'))) { throw new \InvalidArgumentException('The argument $includeOrExclude must be one of "include" or "exclude", the given value was not allowed.', 1423726253); } foreach ($filterConfiguration as $packageKey => $filterExpressions) { if (!array_key_exists($packageKey, $classNames)) { $this->systemLogger->log('The package "' . $packageKey . '" specified in the setting "TYPO3.Flow.object.' . $includeOrExclude . 'Classes" was either excluded or is not loaded.', LOG_DEBUG); continue; } if (!is_array($filterExpressions)) { throw new \TYPO3\Flow\Configuration\Exception\InvalidConfigurationTypeException('The value given for setting "TYPO3.Flow.object.' . $includeOrExclude . 'Classes.\'' . $packageKey . '\'" is invalid. It should be an array of expressions. Check the syntax in the YAML file.', 1422357272); } $classesForPackageUnderInspection = $classNames[$packageKey]; $classNames[$packageKey] = array(); foreach ($filterExpressions as $filterExpression) { $classesForPackageUnderInspection = array_filter($classesForPackageUnderInspection, function ($className) use($filterExpression, $includeOrExclude) { $match = preg_match('/' . $filterExpression . '/', $className); return $includeOrExclude === 'include' ? $match === 1 : $match !== 1; }); if ($includeOrExclude === 'include') { $classNames[$packageKey] = array_merge($classNames[$packageKey], $classesForPackageUnderInspection); $classesForPackageUnderInspection = $classNames[$packageKey]; } else { $classNames[$packageKey] = $classesForPackageUnderInspection; } } if ($classNames[$packageKey] === array()) { unset($classNames[$packageKey]); } } return $classNames; }
/** * Checks if the specified method matches with the method annotation filter pattern * * @param string $className Name of the class to check against - not used here * @param string $methodName Name of the method * @param string $methodDeclaringClassName Name of the class the method was originally declared in * @param mixed $pointcutQueryIdentifier Some identifier for this query - must at least differ from a previous identifier. Used for circular reference detection - not used here * @return boolean TRUE if the class matches, otherwise FALSE */ public function matches($className, $methodName, $methodDeclaringClassName, $pointcutQueryIdentifier) { if ($methodDeclaringClassName === null || !method_exists($methodDeclaringClassName, $methodName)) { return false; } $designatedAnnotations = $this->reflectionService->getMethodAnnotations($methodDeclaringClassName, $methodName, $this->annotation); if ($designatedAnnotations !== array() || $this->annotationValueConstraints === array()) { $matches = $designatedAnnotations !== array(); } else { // It makes no sense to check property values for an annotation that is used multiple times, we shortcut and check the value against the first annotation found. $firstFoundAnnotation = $designatedAnnotations; $annotationProperties = $this->reflectionService->getClassPropertyNames($this->annotation); foreach ($this->annotationValueConstraints as $propertyName => $expectedValue) { if (!array_key_exists($propertyName, $annotationProperties)) { $this->systemLogger->log('The property "' . $propertyName . '" declared in pointcut does not exist in annotation ' . $this->annotation, LOG_NOTICE); return false; } if ($firstFoundAnnotation->{$propertyName} === $expectedValue) { $matches = true; } else { return false; } } } return $matches; }
/** * Iterates over all existing sessions and removes their data if the inactivity * timeout was reached. * * @param boolean $maximumSessionsToRemove How many sessions to remove per run * @return integer The number of outdated entries removed * @api */ public function collectGarbage($maximumSessionsToRemove = 0) { if ($this->inactivityTimeout === 0) { return 0; } if ($this->metaDataCache->has('_garbage-collection-running')) { return false; } $sessionRemovalCount = 0; $this->metaDataCache->set('_garbage-collection-running', true, array(), 120); foreach ($this->metaDataCache->getIterator() as $sessionIdentifier => $sessionInfo) { if ($sessionIdentifier === '_garbage-collection-running') { continue; } $lastActivitySecondsAgo = $this->now - $sessionInfo['lastActivityTimestamp']; if ($lastActivitySecondsAgo > $this->inactivityTimeout) { if ($sessionInfo['storageIdentifier'] === null) { $this->systemLogger->log('SESSION INFO INVALID: ' . $sessionIdentifier, LOG_WARNING, $sessionInfo); } else { $this->storageCache->flushByTag($sessionInfo['storageIdentifier']); $sessionRemovalCount++; } $this->metaDataCache->remove($sessionIdentifier); } if ($maximumSessionsToRemove > 0 && $sessionRemovalCount >= $maximumSessionsToRemove) { break; } } $this->metaDataCache->remove('_garbage-collection-running'); return $sessionRemovalCount; }
/** * Checks if the specified method matches against the method name * expression. * * Returns TRUE if method name, visibility and arguments constraints match and the target * method is not final. * * @param string $className Ignored in this pointcut filter * @param string $methodName Name of the method to match against * @param string $methodDeclaringClassName Name of the class the method was originally declared in * @param mixed $pointcutQueryIdentifier Some identifier for this query - must at least differ from a previous identifier. Used for circular reference detection. * @return boolean TRUE if the class matches, otherwise FALSE * @throws \TYPO3\Flow\Aop\Exception */ public function matches($className, $methodName, $methodDeclaringClassName, $pointcutQueryIdentifier) { $matchResult = preg_match('/^' . $this->methodNameFilterExpression . '$/', $methodName); if ($matchResult === false) { throw new \TYPO3\Flow\Aop\Exception('Error in regular expression', 1168876915); } elseif ($matchResult !== 1) { return false; } switch ($this->methodVisibility) { case 'public': if (!($methodDeclaringClassName !== null && $this->reflectionService->isMethodPublic($methodDeclaringClassName, $methodName))) { return false; } break; case 'protected': if (!($methodDeclaringClassName !== null && $this->reflectionService->isMethodProtected($methodDeclaringClassName, $methodName))) { return false; } break; } if ($methodDeclaringClassName !== null && $this->reflectionService->isMethodFinal($methodDeclaringClassName, $methodName)) { return false; } $methodArguments = $methodDeclaringClassName === null ? array() : $this->reflectionService->getMethodParameters($methodDeclaringClassName, $methodName); foreach (array_keys($this->methodArgumentConstraints) as $argumentName) { $objectAccess = explode('.', $argumentName, 2); $argumentName = $objectAccess[0]; if (!array_key_exists($argumentName, $methodArguments)) { $this->systemLogger->log('The argument "' . $argumentName . '" declared in pointcut does not exist in method ' . $methodDeclaringClassName . '->' . $methodName, LOG_NOTICE); return false; } } return true; }
/** * Detects changes of the files and directories to be monitored and emits signals * accordingly. * * @return void * @api */ public function detectChanges() { if ($this->changedFiles === null || $this->changedPaths === null) { $this->loadDetectedDirectoriesAndFiles(); $changesDetected = false; $this->changedPaths = $this->changedFiles = array(); $this->changedFiles = $this->detectChangedFiles($this->monitoredFiles); foreach ($this->monitoredDirectories as $path => $filenamePattern) { $changesDetected = $this->detectChangesOnPath($path, $filenamePattern) ? true : $changesDetected; } if ($changesDetected) { $this->saveDetectedDirectoriesAndFiles(); } $this->directoriesAndFiles = null; } $changedFileCount = count($this->changedFiles); $changedPathCount = count($this->changedPaths); if ($changedFileCount > 0) { $this->emitFilesHaveChanged($this->identifier, $this->changedFiles); } if ($changedPathCount > 0) { $this->emitDirectoriesHaveChanged($this->identifier, $this->changedPaths); } if ($changedFileCount > 0 || $changedPathCount) { $this->systemLogger->log(sprintf('File Monitor "%s" detected %s changed files and %s changed directories.', $this->identifier, $changedFileCount, $changedPathCount), LOG_INFO); } }
/** * Deletes the given Resource from the Resource Repository and, if the storage data is no longer used in another * Resource object, also deletes the data from the storage. * * This method will also remove the Resource object from the (internal) ResourceRepository. * * @param Resource $resource The resource to delete * @param boolean $unpublishResource If the resource should be unpublished before deleting it from the storage * @return boolean TRUE if the resource was deleted, otherwise FALSE * @api */ public function deleteResource(Resource $resource, $unpublishResource = TRUE) { $collectionName = $resource->getCollectionName(); $result = $this->resourceRepository->findBySha1($resource->getSha1()); if (count($result) > 1) { $this->systemLogger->log(sprintf('Not removing storage data of resource %s (%s) because it is still in use by %s other Resource object(s).', $resource->getFilename(), $resource->getSha1(), count($result) - 1), LOG_DEBUG); } else { if (!isset($this->collections[$collectionName])) { $this->systemLogger->log(sprintf('Could not remove storage data of resource %s (%s) because it refers to the unknown collection "%s".', $resource->getFilename(), $resource->getSha1(), $collectionName), LOG_WARNING); return FALSE; } $storage = $this->collections[$collectionName]->getStorage(); if (!$storage instanceof WritableStorageInterface) { $this->systemLogger->log(sprintf('Could not remove storage data of resource %s (%s) because it its collection "%s" is read-only.', $resource->getFilename(), $resource->getSha1(), $collectionName), LOG_WARNING); return FALSE; } try { $storage->deleteResource($resource); } catch (\Exception $exception) { $this->systemLogger->log(sprintf('Could not remove storage data of resource %s (%s): %s.', $resource->getFilename(), $resource->getSha1(), $exception->getMessage()), LOG_WARNING); return FALSE; } if ($unpublishResource) { /** @var TargetInterface $target */ $target = $this->collections[$collectionName]->getTarget(); $target->unpublishResource($resource); $this->systemLogger->log(sprintf('Removed storage data and unpublished resource %s (%s) because it not used by any other Resource object.', $resource->getFilename(), $resource->getSha1()), LOG_DEBUG); } else { $this->systemLogger->log(sprintf('Removed storage data of resource %s (%s) because it not used by any other Resource object.', $resource->getFilename(), $resource->getSha1()), LOG_DEBUG); } } $resource->setDeleted(); $this->resourceRepository->remove($resource); return TRUE; }
/** * @return void */ public function flush() { try { $this->documentManager->flush(); } catch (\Exception $exception) { $this->systemLogger->log('Could not flush ODM unit of work, error: ' . $exception->getMessage()); } }
/** * Sends a mail and creates a system logger entry if sending failed * * @param Message $mail * @return boolean TRUE on success, otherwise FALSE */ protected function sendMail(Message $mail) { $numberOfRecipients = 0; // ignore exceptions but log them $exceptionMessage = ''; try { $numberOfRecipients = $mail->send(); } catch (\Exception $e) { $this->systemLogger->logException($e); $exceptionMessage = $e->getMessage(); } if ($numberOfRecipients < 1) { $this->systemLogger->log('Could not send notification email "' . $mail->getSubject() . '"', LOG_ERR, ['exception' => $exceptionMessage, 'message' => $mail->getSubject(), 'id' => (string) $mail->getHeaders()->get('Message-ID')]); return false; } return true; }
/** * 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; }
/** * Validates tokenClasses and CAS-client settings by given cas provider. * WARNING: Given provider must be of type RafaelKa\JasigPhpCas\Authentication\Provider\PhpCasAuthenticationProvider * validateConfigurationForCasProvider. * * @todo move validation to other class. * * @param string $providerName defined in Settings.yaml providers name * * @throws \RafaelKa\JasigPhpCas\Exception\InvalidArgumentException * @throws \RafaelKa\JasigPhpCas\Exception\InvalidConfigurationException * * @return bool */ public function validateCASSettingsByProvider($providerName) { $provider = $this->configurationManager->getConfiguration(\TYPO3\Flow\Configuration\ConfigurationManager::CONFIGURATION_TYPE_SETTINGS, 'TYPO3.Flow.security.authentication.providers.' . $providerName); if (empty($provider)) { throw new \RafaelKa\JasigPhpCas\Exception\InvalidArgumentException(sprintf('"%s" - provider does not exists.', $providerName), 1371136764); } if ($provider['provider'] !== self::DEFAULT_CAS_PROVIDER) { throw new \RafaelKa\JasigPhpCas\Exception\InvalidArgumentException(sprintf('Bad parameter for $providerName given in "%s()". The "%s" is not "%s". Please make sure that TYPO3.Flow.security.authentication.providers.%s.provider is "%s" or don\'t validate this provider with "%s->%s()".', __FUNCTION__, $providerName, self::DEFAULT_CAS_PROVIDER, $providerName, self::DEFAULT_CAS_PROVIDER, __CLASS__, __FUNCTION__), 1370963205); } // tokenClasses can be ommitted but if is set, then properly ;) if (!empty($provider['tokenClasses']) && is_array($provider['tokenClasses'])) { foreach ($provider['tokenClasses'] as $tokenClassName) { if (!class_exists($tokenClassName)) { throw new \RafaelKa\JasigPhpCas\Exception\InvalidConfigurationException(sprintf('Class "%s" configured in Settings.yaml at "TYPO3.Flow.security.authentication.providers.%s.tokenClasses" does not exists.', $tokenClassName, $providerName), 1370947266); } if (!$this->reflectionService->isClassImplementationOf($tokenClassName, 'TYPO3\\Flow\\Security\\Authentication\\TokenInterface')) { throw new \RafaelKa\JasigPhpCas\Exception\InvalidConfigurationException(sprintf('Class "%s" configured in Settings.yaml at "TYPO3.Flow.security.authentication.providers.%s.tokenClasses" is not implementation of "\\TYPO3\\Flow\\Security\\Authentication\\TokenInterface". Please rediclare "%s" as "\\TYPO3\\Flow\\Security\\Authentication\\TokenInterface" adapter Class.', $tokenClassName, $providerName, $tokenClassName), 1370947266); } } } elseif (isset($provider['tokenClasses']) && !is_array($provider['tokenClasses'])) { throw new \RafaelKa\JasigPhpCas\Exception\InvalidConfigurationException(sprintf('The configuration setting for TYPO3.Flow.security.authentication.providers.%s.tokenClasses is set but empty or is not an array. This option can be ommited but if it is set, then must contain a list(yaml array with - ) of token class names, which this provider can authenticate.', $providerName), 1371140452); } // cas Client Settings : required if (empty($provider['providerOptions']['casClient'])) { throw new \TYPO3\Flow\Security\Exception\MissingConfigurationException(sprintf('The configuration setting for TYPO3.Flow.security.authentication.providers.%s.providerOptions.casClient is missing. Please specify it in your Settings.yaml file. Beware: This file must not be accessible by the public!', $providerName), 1370797663); } if (empty($provider['providerOptions']['casClient']['server_hostname'])) { throw new \TYPO3\Flow\Security\Exception\MissingConfigurationException(sprintf('The configuration setting for TYPO3.Flow.security.authentication.providers.%s.providerOptions.casClient.server_hostname is missing. Please specify it in your Settings.yaml file. Beware: This file must not be accessible by the public!', $providerName), 1370797665); } if (empty($provider['providerOptions']['casClient']['server_uri'])) { throw new \TYPO3\Flow\Security\Exception\MissingConfigurationException(sprintf('The configuration setting for TYPO3.Flow.security.authentication.providers.%s.providerOptions.casClient.server_uri is missing. Please specify it in your Settings.yaml file. Beware: This file must not be accessible by the public!', $providerName), 1370797667); } if (empty($provider['providerOptions']['casClient']['noCasServerValidation']) || $provider['providerOptions']['casClient']['noCasServerValidation'] === false) { if (empty($provider['providerOptions']['casClient']['casServerCACertificatePath'])) { throw new \TYPO3\Flow\Security\Exception\MissingConfigurationException(sprintf('The configuration setting for TYPO3.Flow.security.authentication.providers.%s.providerOptions.casClient.casServerCACertificatePath is missing. Please specify it in your Settings.yaml file. Beware: This file must not be accessible by the public!', $providerName), 1370797668); } elseif (!is_readable($provider['providerOptions']['casClient']['casServerCACertificatePath'])) { throw new \RafaelKa\JasigPhpCas\Exception\InvalidConfigurationException(sprintf('Certificate "%s" difined in "TYPO3.Flow.security.authentication.providers.%s.providerOptions.casClient.casServerCACertificatePath" does not exists or is not readable. Please specify it correctly in your Settings.yaml file or make it readable. Beware: This both files must not be accessible by the public!', $provider['providerOptions']['casClient']['casServerCACertificatePath'], $providerName), 1370775324); } } else { // @todo : LOG WARNING -> WARNING: Beware: sprintf('[Warning:] Set TYPO3.Flow.security.authentication.providers.%s.providerOptions.casClient.noCasServerValidation to TRUE in your Settings.yaml file makes CAS-Provider insecure. Please set it to FALSE and TYPO3.Flow.security.authentication.providers.%s.providerOptions.casClient.casServerCACertificatePath correctly.', $providerName, $providerName); $this->systemLogger->log(sprintf('[Warning:] Set TYPO3.Flow.security.authentication.providers.%s.providerOptions.casClient.noCasServerValidation to TRUE in your Settings.yaml file makes CAS-Provider insecure. Please set it to FALSE and TYPO3.Flow.security.authentication.providers.%s.providerOptions.casClient.casServerCACertificatePath correctly.', $providerName, $providerName), LOG_NOTICE); } // Mapper class if set if (!empty($provider['providerOptions']['Mapping']['MapperClass'])) { $mapperClassName = $provider['providerOptions']['Mapping']['MapperClass']; if (!class_exists($mapperClassName)) { throw new \RafaelKa\JasigPhpCas\Exception\InvalidConfigurationException(sprintf('Class "%s" configured in Settings.yaml at "TYPO3.Flow.security.authentication.providers.%s.Mapping.MapperClass" does not exists.', $mapperClassName, $providerName), 1370983932); } if (!$this->reflectionService->isClassImplementationOf($mapperClassName, 'RafaelKa\\JasigPhpCas\\Service\\MapperInterface')) { throw new \RafaelKa\JasigPhpCas\Exception\InvalidClassDefinitionForMapperException(sprintf('Class "%s" configured in Settings.yaml at "TYPO3.Flow.security.authentication.providers.%s.MapperClass" is not implementation of "RafaelKa\\JasigPhpCas\\Service\\MapperInterface". Please rediclare "%s" as "\\TYPO3\\Flow\\Security\\Authentication\\TokenInterface" adapter Class. Don\'t forget to flush caches.', $mapperClassName, $providerName, $mapperClassName), 1370981664); } if ($this->reflectionService->getClassAnnotation($mapperClassName, 'TYPO3\\Flow\\Annotations\\Scope')->value !== 'singleton') { throw new \RafaelKa\JasigPhpCas\Exception\InvalidClassDefinitionForMapperException(sprintf('Class "%s" configured in Settings.yaml at "TYPO3.Flow.security.authentication.providers.%s.MapperClass" is not a singleton. Please declare "%s" as "@Flow\\Scope("singleton")" Class.', $mapperClassName, $providerName, $mapperClassName), 1371036890); } } return true; }
/** * 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; }
/** * This function tries to find yet unmatched dependencies which need to be injected via "inject*" setter methods. * * @param array &$objectConfigurations * @return void * @throws \TYPO3\Flow\Object\Exception if an injected property is private */ protected function autowireProperties(array &$objectConfigurations) { foreach ($objectConfigurations as $objectConfiguration) { $className = $objectConfiguration->getClassName(); $properties = $objectConfiguration->getProperties(); $classMethodNames = get_class_methods($className); if (!is_array($classMethodNames)) { if (!class_exists($className)) { throw new \TYPO3\Flow\Object\Exception\UnknownClassException(sprintf('The class "%s" defined in the object configuration for object "%s", defined in package: %s, does not exist.', $className, $objectConfiguration->getObjectName(), $objectConfiguration->getPackageKey()), 1352371371); } else { throw new \TYPO3\Flow\Object\Exception\UnknownClassException(sprintf('Could not autowire properties of class "%s" because names of methods contained in that class could not be retrieved using get_class_methods().', $className), 1352386418); } } foreach ($classMethodNames as $methodName) { if (strlen($methodName) > 6 && substr($methodName, 0, 6) === 'inject' && $methodName[6] === strtoupper($methodName[6])) { $propertyName = lcfirst(substr($methodName, 6)); $autowiringAnnotation = $this->reflectionService->getMethodAnnotation($className, $methodName, 'TYPO3\\Flow\\Annotations\\Autowiring'); if ($autowiringAnnotation !== NULL && $autowiringAnnotation->enabled === FALSE) { continue; } if ($methodName === 'injectSettings') { $packageKey = $objectConfiguration->getPackageKey(); if ($packageKey !== NULL) { $properties[$propertyName] = new ConfigurationProperty($propertyName, $packageKey, ConfigurationProperty::PROPERTY_TYPES_SETTING); } } else { if (array_key_exists($propertyName, $properties)) { continue; } $methodParameters = $this->reflectionService->getMethodParameters($className, $methodName); if (count($methodParameters) !== 1) { $this->systemLogger->log(sprintf('Could not autowire property %s because %s() expects %s instead of exactly 1 parameter.', "{$className}::{$propertyName}", $methodName, count($methodParameters) ?: 'none'), LOG_DEBUG); continue; } $methodParameter = array_pop($methodParameters); if ($methodParameter['class'] === NULL) { $this->systemLogger->log(sprintf('Could not autowire property %s because the method parameter in %s() contained no class type hint.', "{$className}::{$propertyName}", $methodName), LOG_DEBUG); continue; } $properties[$propertyName] = new ConfigurationProperty($propertyName, $methodParameter['class'], ConfigurationProperty::PROPERTY_TYPES_OBJECT); } } } foreach ($this->reflectionService->getPropertyNamesByAnnotation($className, 'TYPO3\\Flow\\Annotations\\Inject') as $propertyName) { if ($this->reflectionService->isPropertyPrivate($className, $propertyName)) { $exceptionMessage = 'The property "' . $propertyName . '" in class "' . $className . '" must not be private when annotated for injection.'; throw new \TYPO3\Flow\Object\Exception($exceptionMessage, 1328109641); } if (!array_key_exists($propertyName, $properties)) { $objectName = trim(implode('', $this->reflectionService->getPropertyTagValues($className, $propertyName, 'var')), ' \\'); $properties[$propertyName] = new ConfigurationProperty($propertyName, $objectName, ConfigurationProperty::PROPERTY_TYPES_OBJECT); } } $objectConfiguration->setProperties($properties); } }
/** * Return the total number of hits for the query. * * @return integer */ public function count() { $timeBefore = microtime(TRUE); $count = parent::count(); $timeAfterwards = microtime(TRUE); if ($this->queryLogEnabled === TRUE) { $this->logger->log('Query Log (' . $this->logMessage . '): -- execution time: ' . ($timeAfterwards - $timeBefore) * 1000 . ' ms -- Total Results: ' . $count, LOG_DEBUG); } return $count; }
/** * Flushes I18n caches if translation files have changed * * @param array $changedFiles A list of full paths to changed files * @return void * @see flushSystemCachesByChangedFiles() */ protected function flushTranslationCachesByChangedFiles(array $changedFiles) { foreach ($changedFiles as $pathAndFilename => $status) { if (preg_match('/\\/Translations\\/.+\\.xlf/', $pathAndFilename) === 1) { $this->systemLogger->log('The localization files have changed, thus flushing the I18n XML model cache.', LOG_INFO); $this->getCache('Flow_I18n_XmlModelCache')->flush(); break; } } }
/** * Refreshes this asset after the Resource or any other parameters affecting thumbnails have been modified * * @return void */ public function refresh() { $assetClassType = str_replace('TYPO3\\Media\\Domain\\Model\\', '', get_class($this)); $this->systemLogger->log(sprintf('%s: refresh() called, clearing all thumbnails. Filename: %s. Resource SHA1: %s', $assetClassType, $this->getResource()->getFilename(), $this->getResource()->getSha1()), LOG_DEBUG); // whitelist objects so they can be deleted (even during safe requests) $this->persistenceManager->whitelistObject($this); foreach ($this->thumbnails as $thumbnail) { $this->persistenceManager->whitelistObject($thumbnail); } $this->thumbnails->clear(); }
/** * @param callable $callback a callback function to process every notification * @return void * @api */ public function flush(callable $callback = null) { foreach ($this->messages as $message) { /** @var Message $message */ $this->messages->detach($message); $this->systemLogger->log('ResourcePublishingMessage: ' . $message->getMessage(), $message->getSeverity()); if ($callback !== null) { $callback($message); } } }
/** * Logs calls of collectGarbage() * * @Flow\AfterReturning("within(TYPO3\Flow\Session\SessionInterface) && method(.*->collectGarbage())") * @param \TYPO3\Flow\Aop\JoinPointInterface $joinPoint The current joinpoint * @return void */ public function logCollectGarbage(\TYPO3\Flow\Aop\JoinPointInterface $joinPoint) { $sessionRemovalCount = $joinPoint->getResult(); if ($sessionRemovalCount > 0) { $this->systemLogger->log(sprintf('%s: Triggered garbage collection and removed %s expired sessions.', $this->getClassName($joinPoint), $sessionRemovalCount), LOG_INFO); } elseif ($sessionRemovalCount === 0) { $this->systemLogger->log(sprintf('%s: Triggered garbage collection but no sessions needed to be removed.', $this->getClassName($joinPoint)), LOG_INFO); } elseif ($sessionRemovalCount === false) { $this->systemLogger->log(sprintf('%s: Ommitting garbage collection because another process is already running. Consider lowering the GC propability if these messages appear a lot.', $this->getClassName($joinPoint)), LOG_WARNING); } }