Skip to content
Snippets Groups Projects
Commit 2d4040b3 authored by Stefan Galinski's avatar Stefan Galinski :video_game:
Browse files

[BUGFIX] The registration may working the first time secure now, also fixed dozens of more bugs

parent 39350792
No related branches found
No related tags found
1 merge request!11Feature security update
......@@ -29,6 +29,7 @@ namespace SGalinski\SgMail\Controller;
use SGalinski\SgMail\Domain\Model\Template;
use SGalinski\SgMail\Service\BackendService;
use SGalinski\SgMail\Service\MailTemplateService;
use SGalinski\SgMail\Service\RegisterService;
use SGalinski\SgMail\Session\PhpSession;
use TYPO3\CMS\Backend\Template\Components\DocHeaderComponent;
use TYPO3\CMS\Backend\Utility\BackendUtility;
......@@ -102,22 +103,22 @@ class MailController extends ActionController {
$this->redirect('index', $this->session->getDataByKey('mode'));
}
$registerArray = BackendService::getNonBlacklistedTemplates($pid);
$removeExtensionKeys = [];
$registerArray = BackendService::getNonBlacklistedTemplates($pid);
foreach ($registerArray as $extensionKey => $extensionTemplates) {
if (\count($extensionTemplates) === 0) {
$removeExtensionKeys[] = $extensionKey;
}
}
foreach ($removeExtensionKeys as $extensionKey) {
unset($registerArray[$extensionKey]);
}
reset($registerArray);
// if no extensions are registered, redirect to empty action
if (empty($registerArray)) {
$this->redirect('empty');
if (!\is_array($registerArray) || \count($registerArray) <= 0) {
$this->forward('empty');
}
// if no template & extensionKey is selected look for them in the session
......@@ -126,7 +127,8 @@ class MailController extends ActionController {
$this->session->getDataByKey('selectedTemplate') !== NULL &&
$this->session->getDataByKey('selectedExtension') !== NULL &&
!MailTemplateService::isTemplateBlacklisted(
$this->session->getDataByKey('selectedExtension'), $this->session->getDataByKey('selectedTemplate'),
$this->session->getDataByKey('selectedExtension'),
$this->session->getDataByKey('selectedTemplate'),
$pid
)
) {
......@@ -365,12 +367,13 @@ class MailController extends ActionController {
*
* @TODO remove this with version 5.0.0
* @return array
* @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException
*/
private function getDeprecationWarnings(): array {
debug($GLOBALS['sg_mail']);
$deprecationWarnings = [];
$extensionList = ExtensionManagementUtility::getLoadedExtensionListArray();
$registerService = $this->objectManager->get(RegisterService::class);
$registerArray = $registerService->getRegisterArray();
foreach ($extensionList as $extensionName) {
$extensionConfigDirectory = ExtensionManagementUtility::extPath($extensionName) .
MailTemplateService::CONFIG_PATH;
......@@ -385,18 +388,15 @@ class MailController extends ActionController {
continue;
}
// already registered in the new way?
if (!isset($GLOBALS['sg_mail'][$extensionName][$configFile])) {
continue;
}
$registrationArray = include $pathToRegistrationFile;
$extensionKey = $registrationArray['extension_key'];
$templateKey = $registrationArray['template_key'];
// provide code example on how to register correctly
$code = '$GLOBALS[\'sg_mail\'][\'' . $extensionName . '\'][\'' . $templateKey . '\'] = \'EXT:' .
$extensionName . '/' . MailTemplateService::CONFIG_PATH . '/' . $configFile . '\';';
$deprecationWarnings[] = ['code' => $code];
if ($registerArray[$extensionKey][$templateKey]['insecureRegistration']) {
$code = '$GLOBALS[\'sg_mail\'][\'' . $extensionKey . '\'][\'' . $templateKey . '\'] = \'EXT:' .
$extensionName . '/' . MailTemplateService::CONFIG_PATH . '/' . $configFile . '\';';
$deprecationWarnings[] = ['code' => $code];
}
}
}
......
......@@ -100,7 +100,6 @@ class FormsFinisher extends AbstractFinisher {
$ignoreMailQueue = (boolean) $this->parseOption('ignoreMailQueue');
$objectManager = GeneralUtility::makeInstance(ObjectManager::class);
/** @var \SGalinski\SgMail\Service\MailTemplateService $mailTemplateService */
$mailTemplateService = $objectManager->get(
MailTemplateService::class, $templateName, 'sg_mail', $markers
);
......
......@@ -36,11 +36,9 @@ use TYPO3\CMS\Core\Database\DatabaseConnection;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Domain\Repository\FrontendUserRepository;
use TYPO3\CMS\Extbase\Mvc\Request;
use TYPO3\CMS\Extbase\Object\ObjectManager;
use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager;
use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings;
use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
......@@ -70,7 +68,7 @@ class BackendService {
* @return array
* @throws \InvalidArgumentException
*/
public static function getPages() {
public static function getPages(): array {
$out = [];
/** @var $databaseConnection DatabaseConnection */
$databaseConnection = $GLOBALS['TYPO3_DB'];
......@@ -139,7 +137,7 @@ class BackendService {
* @param int $currentPid
* @return int
*/
public static function getSiteRoot($currentPid) {
public static function getSiteRoot($currentPid): int {
$rootLine = BackendUtility::BEgetRootLine((int) $currentPid);
$siteRoot = ['uid' => 0];
......@@ -165,7 +163,7 @@ class BackendService {
*/
public static function getSelectedTemplates(
$selectedExtension, $selectedTemplate, array $languages, $pid
) {
): array {
$selectedTemplates = [];
$objectManager = GeneralUtility::makeInstance(ObjectManager::class);
......@@ -187,7 +185,7 @@ class BackendService {
* @return array
* @throws \InvalidArgumentException
*/
public static function getLanguages() {
public static function getLanguages(): array {
/** @var $databaseConnection DatabaseConnection */
$databaseConnection = $GLOBALS['TYPO3_DB'];
/** @var QueryResultInterface $rows */
......@@ -219,7 +217,7 @@ class BackendService {
* @return array
* @throws \InvalidArgumentException
*/
public static function getLanguageLabels(array $languages) {
public static function getLanguageLabels(array $languages): array {
$languageLabels = [];
foreach ($languages as $language) {
......@@ -235,12 +233,12 @@ class BackendService {
* @return array
* @throws \InvalidArgumentException
*/
public static function getLanguagesForFilter() {
public static function getLanguagesForFilter(): array {
$languages = self::getLanguages();
array_unshift($languages, ['isocode' => '', 'name' => '']);
$filterLanguages = [];
if (count($languages) > 0) {
if (\count($languages) > 0) {
foreach ($languages as $language) {
$filterLanguages[$language['isocode']] = $language['name'];
}
......@@ -285,9 +283,9 @@ class BackendService {
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException
*/
public static function saveTemplate($pid, $selectedExtension, $selectedTemplate, $language, $templateData) {
public static function saveTemplate($pid, $selectedExtension, $selectedTemplate, $language, $templateData
): Template {
$objectManager = GeneralUtility::makeInstance(ObjectManager::class);
/** @var TemplateRepository $templateRepository */
$templateRepository = $objectManager->get(TemplateRepository::class);
/** @var Template $template */
......@@ -335,7 +333,7 @@ class BackendService {
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
* @throws \InvalidArgumentException
*/
public static function getCsvFromQueue(array $filters = []) {
public static function getCsvFromQueue(array $filters = []): string {
$objectManager = GeneralUtility::makeInstance(ObjectManager::class);
/** @var MailRepository $mailRepository */
$mailRepository = $objectManager->get(MailRepository::class);
......@@ -343,7 +341,7 @@ class BackendService {
$pageUid = (int) GeneralUtility::_GP('id');
/** @var array $queue */
$queue = $mailRepository->findAllEntries($pageUid, 0, $filters);
$totalQueueSize = count($queue);
$totalQueueSize = \count($queue);
$exportString = '';
if ($totalQueueSize && $queue) {
......@@ -359,7 +357,7 @@ class BackendService {
if ($first) {
$first = FALSE;
foreach ($mail as $field => $value) {
if (!in_array($field, $ignoreFields, TRUE)) {
if (!\in_array($field, $ignoreFields, TRUE)) {
$label = isset($GLOBALS['TCA']['tx_sgmail_domain_model_mail']['columns'][$field]) ?
$GLOBALS['TCA']['fe_users']['columns'][$field]['label'] : '';
if (strpos($label, 'LLL:') === 0) {
......@@ -375,8 +373,8 @@ class BackendService {
/** @var array $mail */
foreach ($queue as $mail) {
foreach ($mail as $field => $value) {
if (!in_array($field, $ignoreFields, TRUE)) {
if (in_array($field, $dateFields, TRUE)) {
if (!\in_array($field, $ignoreFields, TRUE)) {
if (\in_array($field, $dateFields, TRUE)) {
$export[$line][] = $value ? date('d.m.Y', $value) : '';
} else {
$export[$line][] = (string) $value;
......@@ -413,8 +411,7 @@ class BackendService {
$registerService = GeneralUtility::makeInstance(RegisterService::class);
$registerArray = $registerService->getRegisterArray();
$extensionConfiguration = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['sg_mail'], []);
$extensionConfiguration = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['sg_mail'], ['array']);
if (isset($extensionConfiguration['excludeTemplates']) && $extensionConfiguration['excludeTemplates'] !== '') {
$excludedTemplatesWithSiteId = GeneralUtility::trimExplode(
';', $extensionConfiguration['excludeTemplates'], TRUE
......@@ -433,7 +430,7 @@ class BackendService {
}
}
// filter out excluded templates from all domains
// filter out excluded templates from all domains
if (isset($extensionConfiguration['excludeTemplatesAllDomains']) && $extensionConfiguration['excludeTemplatesAllDomains'] !== '') {
$excludedTemplates = GeneralUtility::trimExplode(
',', $extensionConfiguration['excludeTemplatesAllDomains'], TRUE
......
......@@ -166,14 +166,10 @@ class MailTemplateService {
/** @var ObjectManager objectManager */
$this->objectManager = GeneralUtility::makeInstance(ObjectManager::class);
/** @var MailMessage mailMessage */
$this->mailMessage = $this->objectManager->get(MailMessage::class);
/** @var TypoScriptSettingsService $typoScriptSettingsService */
$typoScriptSettingsService = $this->objectManager->get(TypoScriptSettingsService::class);
$tsSettings = $typoScriptSettingsService->getSettings(0, 'tx_sgmail');
/** @var TemplateRepository templateRepository */
$this->templateRepository = $this->objectManager->get(TemplateRepository::class);
/** @var PersistenceManager persistenceManager */
$this->persistenceManager = $this->objectManager->get(PersistenceManager::class);
// use defaultMailFromAddress if it is provided in LocalConfiguration.php; use the sg_mail TS setting as fallback
......@@ -794,7 +790,7 @@ class MailTemplateService {
self::logDeprecation('registerExtensions');
$registrationService = GeneralUtility::makeInstance(RegisterService::class);
// write entries for old extensions intto the file list
// write entries for old extensions into the file list
self::registerExtensions();
return $registrationService->getRegisterArray();
......@@ -815,7 +811,6 @@ class MailTemplateService {
foreach ($extensionList as $extensionName) {
$extensionConfigDirectory = ExtensionManagementUtility::extPath($extensionName);
$extensionConfigDirectory .= self::CONFIG_PATH;
if (!\is_dir($extensionConfigDirectory)) {
continue;
}
......@@ -827,13 +822,6 @@ class MailTemplateService {
continue;
}
// already registered in the new way?
$configFileTest = str_replace('.php', '', $configFile);
$configFileTest = GeneralUtility::camelCaseToLowerCaseUnderscored($configFileTest);
if (isset($GLOBALS['sg_mail'][$extensionName][$configFileTest])) {
continue;
}
$GLOBALS['sg_mail'][$extensionName][$configFile] = $pathToRegistrationFile;
}
}
......
......@@ -38,7 +38,7 @@ use TYPO3\CMS\Extbase\Object\ObjectManager;
class RegisterService implements \TYPO3\CMS\Core\SingletonInterface {
const CACHE_NAME = 'sg_mail_registerArrayCache';
const CACHE_LIFETIME_IN_SECONDS = 86400;
const DEFAULT_TEMPLATE_PATH = 'Resources/Private/Templates/MailTemplates/';
const DEFAULT_TEMPLATE_PATH = 'Resources/Private/Templates/SgMail/';
const CONFIG_PATH = 'Configuration/MailTemplates/Forms';
/**
......@@ -57,23 +57,25 @@ class RegisterService implements \TYPO3\CMS\Core\SingletonInterface {
* @throws \InvalidArgumentException
*/
public function getRegisterArray(): array {
if (\count($this->registerArray) > 1) {
return $this->registerArray;
}
$cacheManager = GeneralUtility::makeInstance(CacheManager::class);
$cache = $cacheManager->getCache(self::CACHE_NAME);
$cacheId = 'sg_mail';
$entry = $cache->get($cacheId);
if (!$entry) {
$this->clearCaches();
$entry = $this->registerExtensions();
if ($entry === NULL) {
$entry = [];
$registerArray = $cache->get('sg_mail');
if (!$registerArray || !\is_array($registerArray)) {
$registerArray = $this->registerExtensions();
if (\is_array($registerArray)) {
$cache->set('sg_mail', $registerArray, [], self::CACHE_LIFETIME_IN_SECONDS);
}
}
$cache->set($cacheId, $entry, [], self::CACHE_LIFETIME_IN_SECONDS);
if (!\is_array($registerArray)) {
$registerArray = [];
}
return $entry;
return $registerArray;
}
/**
......@@ -84,8 +86,28 @@ class RegisterService implements \TYPO3\CMS\Core\SingletonInterface {
private function registerExtensions(): array {
$this->registerArray = [];
foreach ($GLOBALS['sg_mail'] as $extension) {
foreach ($extension as $key => $registerFile) {
// @TODO remove in version 5.0.0
$extensionConfiguration = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['sg_mail'], ['array']);
if (((int) $extensionConfiguration['supportOldRegistrations']) === 0) {
MailTemplateService::registerExtensions();
}
foreach ($GLOBALS['sg_mail'] as $extensionName => $templates) {
foreach ($templates as $templateKey => $registerFile) {
// already registered in the new way? Then don't load the old one again.
// @TODO remove in version 5.0.0
$insecureRegistration = FALSE;
if (strpos($templateKey, '.php')) {
$insecureRegistration = TRUE;
$registerFileTest = str_replace('.php', '', $templateKey);
$registerFileTest = GeneralUtility::camelCaseToLowerCaseUnderscored($registerFileTest);
if (isset($GLOBALS['sg_mail'][$extensionName][$registerFileTest]) ||
isset($GLOBALS['sg_mail']['sg_mail'][$registerFileTest])
) {
continue;
}
}
$registerFile = GeneralUtility::getFileAbsFileName($registerFile);
if (!\is_file($registerFile)) {
continue;
......@@ -94,15 +116,15 @@ class RegisterService implements \TYPO3\CMS\Core\SingletonInterface {
$configArray = (include $registerFile);
$extensionKey = $configArray['extension_key'];
$templateKey = $configArray['template_key'];
if ($extensionKey === NULL || $templateKey === NULL) {
if ($extensionKey === NULL) {
continue;
}
$this->writeRegisterArrayEntry($extensionKey, $templateKey, $configArray);
$this->writeRegisterArrayEntry($extensionKey, $templateKey, $configArray, $insecureRegistration);
}
}
// read automatically created extension registrations and write the entries
// read automatically created extensionName registrations and write the entries
$configurationLocation = $this->getRegistrationPath();
$registerFolder = GeneralUtility::getFileAbsFileName($configurationLocation);
if (\is_dir($registerFolder)) {
......@@ -130,16 +152,10 @@ class RegisterService implements \TYPO3\CMS\Core\SingletonInterface {
continue;
}
$this->writeRegisterArrayEntry($extensionKey, $templateKey, $configArray);
$this->writeRegisterArrayEntry($extensionKey, $templateKey, $configArray, FALSE);
}
}
// @TODO remove in version 5.0.0
$extensionConfiguration = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['sg_mail'], ['array']);
if (((int) $extensionConfiguration['supportOldRegistrations']) === 0) {
MailTemplateService::registerExtensions();
}
return $this->registerArray;
}
......@@ -149,37 +165,28 @@ class RegisterService implements \TYPO3\CMS\Core\SingletonInterface {
* @param string $extensionKey
* @param string $templateKey
* @param array $configArray
* @param bool $transformTemplateFolder
* @param string $storeTemplateExtension
* @param bool $insecureRegistration
*/
private function writeRegisterArrayEntry(
$extensionKey, $templateKey, array $configArray,
$transformTemplateFolder = TRUE, $storeTemplateExtension = ''
$extensionKey, $templateKey, array $configArray, $insecureRegistration = FALSE
) {
// If it is not explicitly set in which extension the html should be located, use the extension set in the template settings
if ($storeTemplateExtension === '') {
$storeTemplateExtension = $extensionKey;
// transform template directory name: your_templates => YourTemplates/
$templateDirectoryParts = GeneralUtility::trimExplode('_', $templateKey);
$templateDirectory = '';
foreach ($templateDirectoryParts as $part) {
$templateDirectory .= \ucfirst($part);
}
// give the option to use the template key as folder name. this is used mainly with auto registering
$templateDirectory = $templateKey;
// by default folders with underscore will be transformed to upper camelcase
if ($transformTemplateFolder) {
// transform template directory name: your_templates => YourTemplates/
$templateDirectoryParts = GeneralUtility::trimExplode('_', $templateKey);
$templateDirectory = '';
foreach ($templateDirectoryParts as $part) {
$templateDirectory .= \ucfirst($part);
}
}
$templateDirectory .= '/';
$templatePath = ExtensionManagementUtility::extPath($storeTemplateExtension) .
self::DEFAULT_TEMPLATE_PATH . $templateDirectory;
if ($configArray['template_path']) {
$templatePath = $configArray[$templateKey];
$templatePath = $configArray['template_path'];
} else {
$templatePath = ExtensionManagementUtility::extPath($extensionKey) .
self::DEFAULT_TEMPLATE_PATH . $templateDirectory;
}
if (!\is_dir($templatePath)) {
$templatePath = '';
}
$description = $configArray['description'];
......@@ -194,7 +201,8 @@ class RegisterService implements \TYPO3\CMS\Core\SingletonInterface {
'extension' => $extensionKey,
'templateName' => $templateKey,
'subject' => $subject,
'templateContent' => $templateContent
'templateContent' => $templateContent,
'insecureRegistration' => $insecureRegistration
];
}
......
......@@ -153,8 +153,8 @@ class FormEditorController extends \TYPO3\CMS\Form\Controller\FormEditorControll
}
// call register function in register service class
$registrationService->clearCaches();
$registrationService->getRegisterArray();
$this->clearCaches();
}
/**
......
......@@ -41,7 +41,6 @@ $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['tx_sgmail_up
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['tx_sgmail_update_languages'] = \SGalinski\SgMail\Updates\UpdateLanguages::class;
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['tx_sgmail_update_german_as_default'] = \SGalinski\SgMail\Updates\UpdateGermanAsDefault::class;
if (TYPO3_MODE === 'BE') {
$tsPath = $extPath . 'Configuration/TypoScript/';
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTypoScriptSetup(file_get_contents($tsPath . 'setup.ts'));
......@@ -56,7 +55,6 @@ $GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'][\TYPO3\CMS\Form\Controller\FormMan
'className' => \SGalinski\SgMail\XClass\Form\FormManagerController::class,
];
// Cache registration
$cacheName = \SGalinski\SgMail\Service\RegisterService::CACHE_NAME;
if (!is_array($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations'][$cacheName])) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment