Skip to content
Snippets Groups Projects
Commit a2d13893 authored by Benni Mack's avatar Benni Mack
Browse files

[BUGFIX] Avoid fatal error with invalid soft reference parser links

When a link href is empty or invalid, TYPO3 now does not
crash anymore.

Resolves: #100958
Releases: main, 12.4
Change-Id: I768d43b72a3abd55af06cd9750ac8a400bc41d63
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/79732


Reviewed-by: default avatarBenni Mack <benni@typo3.org>
Tested-by: default avatarcore-ci <typo3@b13.com>
Tested-by: default avatarBenni Mack <benni@typo3.org>
parent 42456c5b
Branches
Tags
No related merge requests found
......@@ -356,20 +356,19 @@ class LinkElement extends AbstractFormElement
break;
case LinkService::TYPE_EMAIL:
$data = [
'text' => $linkData['email'],
'text' => $linkData['email'] ?? '',
'icon' => $this->iconFactory->getIcon('content-elements-mailform', Icon::SIZE_SMALL)->render(),
];
break;
case LinkService::TYPE_URL:
$data = [
'text' => $linkData['url'],
'text' => $linkData['url'] ?? '',
'icon' => $this->iconFactory->getIcon('apps-pagetree-page-shortcut-external', Icon::SIZE_SMALL)->render(),
];
break;
case LinkService::TYPE_FILE:
/** @var File $file */
$file = $linkData['file'];
$file = $linkData['file'] ?? null;
if ($file instanceof File) {
$data = [
'text' => $file->getPublicUrl(),
......@@ -378,8 +377,7 @@ class LinkElement extends AbstractFormElement
}
break;
case LinkService::TYPE_FOLDER:
/** @var Folder $folder */
$folder = $linkData['folder'];
$folder = $linkData['folder'] ?? null;
if ($folder instanceof Folder) {
$data = [
'text' => $folder->getPublicUrl(),
......@@ -415,7 +413,7 @@ class LinkElement extends AbstractFormElement
break;
case LinkService::TYPE_UNKNOWN:
$data = [
'text' => $linkData['file'],
'text' => $linkData['file'] ?? $linkData['url'] ?? '',
'icon' => $this->iconFactory->getIcon('actions-link', Icon::SIZE_SMALL)->render(),
];
break;
......
......@@ -168,7 +168,7 @@ class TypolinkSoftReferenceParser extends AbstractSoftReferenceParser
$elements[$tokenID . ':' . $idx]['subst'] = [
'type' => 'string',
'tokenID' => $tokenID,
'tokenValue' => $tLP['email'],
'tokenValue' => (string)($tLP['email'] ?? ''),
];
// Output content will be the token instead:
$content = '{softref:' . $tokenID . '}';
......@@ -178,7 +178,7 @@ class TypolinkSoftReferenceParser extends AbstractSoftReferenceParser
$elements[$tokenID . ':' . $idx]['subst'] = [
'type' => 'string',
'tokenID' => $tokenID,
'tokenValue' => $tLP['telephone'],
'tokenValue' => (string)($tLP['telephone'] ?? ''),
];
// Output content will be the token instead:
$content = '{softref:' . $tokenID . '}';
......@@ -188,7 +188,7 @@ class TypolinkSoftReferenceParser extends AbstractSoftReferenceParser
$elements[$tokenID . ':' . $idx]['subst'] = [
'type' => 'external',
'tokenID' => $tokenID,
'tokenValue' => $tLP['url'],
'tokenValue' => (string)($tLP['url'] ?? ''),
];
// Output content will be the token instead:
$content = '{softref:' . $tokenID . '}';
......@@ -218,7 +218,7 @@ class TypolinkSoftReferenceParser extends AbstractSoftReferenceParser
'type' => 'db',
'recordRef' => 'sys_file:' . $linkHandlerValue,
'tokenID' => $tokenID,
'tokenValue' => $tLP['identifier'],
'tokenValue' => (string)$tLP['identifier'],
];
// Output content will be the token instead:
$content = '{softref:' . $tokenID . '}';
......@@ -240,7 +240,7 @@ class TypolinkSoftReferenceParser extends AbstractSoftReferenceParser
'type' => 'db',
'recordRef' => 'pages:' . $tLP['pageuid'],
'tokenID' => $tokenID,
'tokenValue' => $tLP['pageuid'],
'tokenValue' => (string)$tLP['pageuid'],
];
}
// Add type if applicable
......@@ -260,7 +260,7 @@ class TypolinkSoftReferenceParser extends AbstractSoftReferenceParser
'type' => 'db',
'recordRef' => 'tt_content:' . $tLP['anchor'],
'tokenID' => $newTokenID,
'tokenValue' => $tLP['anchor'],
'tokenValue' => (string)$tLP['anchor'],
];
} else {
// Anchor is a hardcoded string
......@@ -273,7 +273,7 @@ class TypolinkSoftReferenceParser extends AbstractSoftReferenceParser
'type' => 'db',
'recordRef' => $tLP['table'] . ':' . $tLP['uid'],
'tokenID' => $tokenID,
'tokenValue' => $content,
'tokenValue' => (string)$content,
];
$content = '{softref:' . $tokenID . '}';
......
......@@ -59,9 +59,9 @@ class TypolinkTagSoftReferenceParser extends AbstractSoftReferenceParser
$elements[$key]['matchString'] = $foundValue;
$elements[$key]['subst'] = [
'type' => 'db',
'recordRef' => 'pages:' . $linkDetails['pageuid'],
'recordRef' => 'pages:' . ($linkDetails['pageuid'] ?? 0),
'tokenID' => $token,
'tokenValue' => $linkDetails['pageuid'],
'tokenValue' => $linkDetails['pageuid'] ?? '',
];
if (isset($pageAndAnchorMatches[2]) && $pageAndAnchorMatches[2] !== '') {
// Anchor is assumed to point to a content elements:
......@@ -90,7 +90,7 @@ class TypolinkTagSoftReferenceParser extends AbstractSoftReferenceParser
$elements[$key]['subst'] = [
'type' => 'external',
'tokenID' => $token,
'tokenValue' => $linkDetails['url'],
'tokenValue' => (string)($linkDetails['url'] ?? ''),
];
} elseif ($linkDetails['type'] === LinkService::TYPE_EMAIL) {
$token = $this->makeTokenID((string)$key);
......@@ -99,7 +99,7 @@ class TypolinkTagSoftReferenceParser extends AbstractSoftReferenceParser
$elements[$key]['subst'] = [
'type' => 'string',
'tokenID' => $token,
'tokenValue' => $linkDetails['email'],
'tokenValue' => (string)($linkDetails['email'] ?? ''),
];
} elseif ($linkDetails['type'] === LinkService::TYPE_TELEPHONE) {
$token = $this->makeTokenID((string)$key);
......@@ -108,7 +108,7 @@ class TypolinkTagSoftReferenceParser extends AbstractSoftReferenceParser
$elements[$key]['subst'] = [
'type' => 'string',
'tokenID' => $token,
'tokenValue' => $linkDetails['telephone'],
'tokenValue' => (string)($linkDetails['telephone'] ?? ''),
];
}
} catch (\Exception $e) {
......
......@@ -83,6 +83,12 @@ class LegacyLinkNotationConverter
// Check for link-handler keyword
[$linkHandlerKeyword, $linkHandlerValue] = explode(':', $linkParameter, 2);
$result['type'] = strtolower(trim($linkHandlerKeyword));
if ($linkHandlerValue === '') {
return [
'type' => LinkService::TYPE_UNKNOWN,
'url' => $linkParameter,
];
}
$result['url'] = $linkParameter;
$result['value'] = $linkHandlerValue;
if ($result['type'] === LinkService::TYPE_RECORD) {
......
......@@ -134,6 +134,17 @@ final class TypoLinkSoftReferenceParserTest extends AbstractSoftReferenceParserT
],
],
],
'link with invalid content' => [
[
'content' => 'Email: andrew@example.com',
'elementKey' => '8695f308356bcca1acac2749152a44a9:0',
'matchString' => 'Email: andrew@example.com',
'error' => 'Couldn\'t decide typolink mode.',
],
[
'error' => 'Couldn\'t decide typolink mode.',
],
],
];
}
......
......@@ -120,6 +120,19 @@ final class TypoLinkTagSoftReferenceParserTest extends AbstractSoftReferencePars
],
],
],
'link with invalid content' => [
[
'content' => '<p><a href="Email: hans@example.com">Click here</a></p>',
'elementKey' => 1,
'matchString' => '<a href="Email: hans@example.com">',
],
[
'subst' => [
'type' => 'string',
'tokenValue' => '',
],
],
],
];
}
......
......@@ -28,7 +28,7 @@ class LegacyLinkBuilder extends AbstractTypolinkBuilder
public function build(array &$linkDetails, string $linkText, string $target, array $conf): LinkResultInterface
{
$tsfe = $this->getTypoScriptFrontendController();
if ($linkDetails['file']) {
if ($linkDetails['file'] ?? false) {
$linkDetails['type'] = LinkService::TYPE_FILE;
$linkLocation = $linkDetails['file'];
// Setting title if blank value to link
......@@ -37,7 +37,7 @@ class LegacyLinkBuilder extends AbstractTypolinkBuilder
$url = $linkLocation;
$url = $this->forceAbsoluteUrl($url, $conf);
$target = $target ?: $this->resolveTargetAttribute($conf, 'fileTarget');
} elseif ($linkDetails['url']) {
} elseif ($linkDetails['url'] ?? false) {
$linkDetails['type'] = LinkService::TYPE_URL;
$target = $target ?: $this->resolveTargetAttribute($conf, 'extTarget');
$linkText = $this->encodeFallbackLinkTextIfLinkTextIsEmpty($linkText, $linkDetails['url']);
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment