‪TYPO3CMS  ‪main
FormProtectionFactory.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Psr\Http\Message\ServerRequestInterface;
34 
44 {
45  public function ‪__construct(
46  protected readonly ‪FlashMessageService $flashMessageService,
47  protected readonly ‪LanguageServiceFactory $languageServiceFactory,
48  protected readonly ‪Registry $registry,
49  protected readonly ‪FrontendInterface $runtimeCache
50  ) {}
51 
57  public function ‪createForType(string $type): ‪AbstractFormProtection
58  {
59  if (!in_array($type, ['installtool', 'frontend', 'backend', 'disabled'], true)) {
60  $type = 'disabled';
61  }
63  if ($this->runtimeCache->has(‪$identifier)) {
64  return $this->runtimeCache->get(‪$identifier);
65  }
66  $classNameAndConstructorArguments = $this->‪getClassNameAndConstructorArguments($type, ‪$GLOBALS['TYPO3_REQUEST'] ?? null);
67  $this->runtimeCache->set(‪$identifier, $this->‪createInstance(...$classNameAndConstructorArguments));
68  return $this->runtimeCache->get(‪$identifier);
69  }
70 
74  public function ‪createFromRequest(ServerRequestInterface $request): ‪AbstractFormProtection
75  {
76  $type = $this->‪determineTypeFromRequest($request);
78  if ($this->runtimeCache->has(‪$identifier)) {
79  return $this->runtimeCache->get(‪$identifier);
80  }
81  $classNameAndConstructorArguments = $this->‪getClassNameAndConstructorArguments($type, $request);
82  $this->runtimeCache->set(‪$identifier, $this->‪createInstance(...$classNameAndConstructorArguments));
83  return $this->runtimeCache->get(‪$identifier);
84  }
85 
89  protected function ‪determineTypeFromRequest(ServerRequestInterface $request): string
90  {
91  if ($this->‪isInstallToolSession($request)) {
92  return 'installtool';
93  }
94  if ($this->‪isFrontendSession($request)) {
95  return 'frontend';
96  }
97  if ($this->‪isBackendSession()) {
98  return 'backend';
99  }
100  return 'disabled';
101  }
102 
111  protected function ‪getClassNameAndConstructorArguments(string $type, ?ServerRequestInterface $request): array
112  {
113  if ($type === 'installtool') {
114  return [
115  InstallToolFormProtection::class,
116  ];
117  }
118  if ($type === 'frontend') {
119  $user = $request ? $request->getAttribute('frontend.user') : ((‪$GLOBALS['TSFE'] ?? null) instanceof ‪TypoScriptFrontendController ? ‪$GLOBALS['TSFE']->fe_user : null);
120  if ($user && isset($user->user['uid'])) {
121  return [
122  FrontendFormProtection::class,
123  $user,
124  ];
125  }
126  }
127  if ($type === 'backend') {
128  $user = ‪$GLOBALS['BE_USER'] ?? null;
129  $isAjaxCall = (bool)($request ? $request->getAttribute('route')?->getOption('ajax') : false);
130  if ($user && isset($user->user['uid'])) {
131  return [
132  BackendFormProtection::class,
133  $user,
134  $this->registry,
135  $this->‪getMessageClosure(
136  $this->languageServiceFactory->createFromUserPreferences($user),
137  $this->flashMessageService->getMessageQueueByIdentifier(),
138  $isAjaxCall
139  ),
140  ];
141  }
142  }
143  // failed to use preferred type, disable form protection
144  return [
145  DisabledFormProtection::class,
146  ];
147  }
148 
152  protected function ‪getIdentifierForType(string $type): string
153  {
154  return 'formprotection-instance-' . hash('xxh3', $type);
155  }
156 
160  protected function ‪isInstallToolSession(ServerRequestInterface $request): bool
161  {
162  return (bool)((int)$request->getAttribute('applicationType') & ‪SystemEnvironmentBuilder::REQUESTTYPE_INSTALL);
163  }
164 
168  protected function ‪isBackendSession(): bool
169  {
170  $user = ‪$GLOBALS['BE_USER'] ?? null;
171  return $user instanceof ‪BackendUserAuthentication && isset($user->user['uid']);
172  }
173 
177  protected function ‪isFrontendSession(ServerRequestInterface $request): bool
178  {
179  $user = $request->getAttribute('frontend.user');
180  return $user instanceof ‪FrontendUserAuthentication && isset($user->user['uid']);
181  }
182 
183  protected function ‪getMessageClosure(‪LanguageService $languageService, ‪FlashMessageQueue $messageQueue, bool $isAjaxCall): \Closure
184  {
185  return static function () use ($languageService, $messageQueue, $isAjaxCall) {
186  $flashMessage = GeneralUtility::makeInstance(
187  FlashMessage::class,
188  $languageService->‪sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:error.formProtection.tokenInvalid'),
189  '',
190  ContextualFeedbackSeverity::ERROR,
191  !$isAjaxCall
192  );
193  $messageQueue->‪enqueue($flashMessage);
194  };
195  }
196 
205  protected function ‪createInstance(string $className, ...$constructorArguments): ‪AbstractFormProtection
206  {
207  if (!class_exists($className)) {
208  throw new \InvalidArgumentException('$className must be the name of an existing class, but actually was "' . $className . '".', 1285352962);
209  }
210  $instance = GeneralUtility::makeInstance($className, ...$constructorArguments);
211  if (!$instance instanceof ‪AbstractFormProtection) {
212  throw new \InvalidArgumentException('$className must be a subclass of ' . AbstractFormProtection::class . ', but actually was "' . $className . '".', 1285353026);
213  }
214  return $instance;
215  }
216 }
‪TYPO3\CMS\Core\Localization\LanguageServiceFactory
Definition: LanguageServiceFactory.php:25
‪TYPO3\CMS\Core\FormProtection\FormProtectionFactory\isBackendSession
‪isBackendSession()
Definition: FormProtectionFactory.php:168
‪TYPO3\CMS\Core\FormProtection\FormProtectionFactory\getMessageClosure
‪getMessageClosure(LanguageService $languageService, FlashMessageQueue $messageQueue, bool $isAjaxCall)
Definition: FormProtectionFactory.php:183
‪TYPO3\CMS\Core\FormProtection\FormProtectionFactory\isFrontendSession
‪isFrontendSession(ServerRequestInterface $request)
Definition: FormProtectionFactory.php:177
‪TYPO3\CMS\Core\FormProtection\FormProtectionFactory\getClassNameAndConstructorArguments
‪array getClassNameAndConstructorArguments(string $type, ?ServerRequestInterface $request)
Definition: FormProtectionFactory.php:111
‪TYPO3\CMS\Core\FormProtection\FormProtectionFactory\getIdentifierForType
‪getIdentifierForType(string $type)
Definition: FormProtectionFactory.php:152
‪TYPO3\CMS\Core\FormProtection\FormProtectionFactory\__construct
‪__construct(protected readonly FlashMessageService $flashMessageService, protected readonly LanguageServiceFactory $languageServiceFactory, protected readonly Registry $registry, protected readonly FrontendInterface $runtimeCache)
Definition: FormProtectionFactory.php:45
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder
Definition: SystemEnvironmentBuilder.php:41
‪TYPO3\CMS\Core\Registry
Definition: Registry.php:33
‪TYPO3\CMS\Core\FormProtection\FormProtectionFactory\determineTypeFromRequest
‪determineTypeFromRequest(ServerRequestInterface $request)
Definition: FormProtectionFactory.php:89
‪TYPO3\CMS\Core\FormProtection\FormProtectionFactory\createFromRequest
‪createFromRequest(ServerRequestInterface $request)
Definition: FormProtectionFactory.php:74
‪TYPO3\CMS\Core\Type\ContextualFeedbackSeverity
‪ContextualFeedbackSeverity
Definition: ContextualFeedbackSeverity.php:25
‪TYPO3\CMS\Core\FormProtection
Definition: AbstractFormProtection.php:16
‪TYPO3\CMS\Core\FormProtection\FormProtectionFactory\createInstance
‪createInstance(string $className,... $constructorArguments)
Definition: FormProtectionFactory.php:205
‪TYPO3\CMS\Core\Localization\LanguageService\sL
‪sL($input)
Definition: LanguageService.php:136
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:60
‪TYPO3\CMS\Core\FormProtection\FormProtectionFactory\isInstallToolSession
‪isInstallToolSession(ServerRequestInterface $request)
Definition: FormProtectionFactory.php:160
‪TYPO3\CMS\Core\Cache\Frontend\FrontendInterface
Definition: FrontendInterface.php:22
‪TYPO3\CMS\Core\FormProtection\AbstractFormProtection
Definition: AbstractFormProtection.php:30
‪TYPO3\CMS\Core\Messaging\FlashMessage
Definition: FlashMessage.php:27
‪TYPO3\CMS\Core\FormProtection\FormProtectionFactory
Definition: FormProtectionFactory.php:44
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
Definition: TypoScriptFrontendController.php:103
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\FormProtection\FormProtectionFactory\createForType
‪createForType(string $type)
Definition: FormProtectionFactory.php:57
‪TYPO3\CMS\Core\Messaging\FlashMessageQueue\enqueue
‪enqueue($message)
Definition: FlashMessageQueue.php:63
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:46
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication
Definition: FrontendUserAuthentication.php:33
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:51
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder\REQUESTTYPE_INSTALL
‪const REQUESTTYPE_INSTALL
Definition: SystemEnvironmentBuilder.php:51
‪TYPO3\CMS\Core\Messaging\FlashMessageQueue
Definition: FlashMessageQueue.php:30
‪TYPO3\CMS\Core\Messaging\FlashMessageService
Definition: FlashMessageService.php:27
‪TYPO3\CMS\Webhooks\Message\$identifier
‪identifier readonly string $identifier
Definition: FileAddedMessage.php:37