Skip to content

Commit

Permalink
#340 add support for security policy header
Browse files Browse the repository at this point in the history
  • Loading branch information
digedag committed Nov 19, 2023
1 parent fdc3028 commit c08035a
Show file tree
Hide file tree
Showing 9 changed files with 122 additions and 179 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ v1.18.0 (??.11.2023)
* BC: Parameter type of exceptions changed in ExceptionHandlerInterface to \Throwable
* Share ViewContext instance of current configuration with current request
* Fixed some PHP 8 issues
* Support for activated content security protection header in backend modules
* Support for activated content security policy header in backend modules
* Improved icon support in backend modules
* BC: impossible to use HTML-Code in title parameter of ToolBox::createModuleLink(). Most likely this was done for icon code. As fix provide icon as option ToolBox::OPTION_ICON_NAME.
* BC: removed public attributes `JScode` and `JScodeArray` in `Sys25\RnBase\Backend\Template\Override\DocumentTemplate`

v1.17.4 (22.09.2023)

Expand Down
5 changes: 2 additions & 3 deletions Classes/Backend/Decorator/BaseDecorator.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
use Sys25\RnBase\Domain\Model\DataInterface;
use Sys25\RnBase\Domain\Model\DataModel;
use Sys25\RnBase\Domain\Model\DomainModelInterface as DomainInterface;
use Sys25\RnBase\Domain\Model\RecordInterface;
use Sys25\RnBase\Utility\Strings;
use Sys25\RnBase\Utility\TYPO3;

Expand Down Expand Up @@ -427,11 +426,11 @@ protected function formatActionMovedown(
/**
* Returns the uid map and sets the pointer to the current element.
*
* @param RecordInterface $item
* @param DomainInterface $item
*
* @return array
*/
protected function getUidMap(RecordInterface $item)
protected function getUidMap(DomainInterface $item)
{
if (!$this->getOptions()->hasUidMap()) {
return [];
Expand Down
5 changes: 5 additions & 0 deletions Classes/Backend/Form/Element/EnhancedLinkButton.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ class EnhancedLinkButton extends LinkButton
{
private $overrideCss = true;

public function addDataAttributes(array $dataAttributes)
{
$this->dataAttributes = array_merge($this->dataAttributes, $dataAttributes);
}

/**
* If set given css classes will override default button classes.
*
Expand Down
179 changes: 89 additions & 90 deletions Classes/Backend/Form/ToolBox.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class ToolBox
public const OPTION_HOVER_TEXT = 'hover';

public const OPTION_PARAMS = 'params';
public const OPTION_DATA_ATTR = 'data-attr';

/**
* Clipboard object.
Expand Down Expand Up @@ -320,14 +321,14 @@ private function buildEditUri($table, $pid, $operation, array $options)
*/
public function createHistoryLink($table, $recordUid, $label = '')
{
$this->addBaseInlineJSCode();
$image = Icons::getSpriteIcon('actions-document-history-open');
$moduleUrl = BackendUtility::getModuleUrl('record_history', ['element' => $table.':'.$recordUid]);
$onClick = 'return jumpExt('.Strings::quoteJSvalue($moduleUrl).',\'#latest\');';
$options = [
self::OPTION_ICON_NAME => 'actions-document-history-open',
];

$btn = $this->createModuleButton($moduleUrl, $label, $options);

return '<a class="btn btn-default" href="#" onclick="'.htmlspecialchars($onClick).'" title="'
.htmlspecialchars($GLOBALS['LANG']->getLL('history')).'">'
.$image.'</a>';
return $btn->render();
}

/**
Expand All @@ -345,15 +346,13 @@ public function createHideLink($table, $uid, $unhide = false, $options = [])
$sEnableColumn = ($sEnableColumn) ? $sEnableColumn : 'hidden';
$label = isset($options['label']) ? $options['label'] : '';

$image = Icons::getSpriteIcon(
$unhide ? 'actions-edit-unhide' : 'actions-edit-hide'
);
$options[self::OPTION_ICON_NAME] = $unhide ? 'actions-edit-unhide' : 'actions-edit-hide';

$options['hover'] = $unhide ? 'Show' : 'Hide UID: '.$uid;

return $this->createLinkForDataHandlerAction(
'data['.$table.']['.$uid.']['.$sEnableColumn.']='.($unhide ? 0 : 1),
$image.$label,
$label,
$options
);
}
Expand All @@ -367,13 +366,23 @@ public function createHideLink($table, $uid, $unhide = false, $options = [])
*/
public function createInfoLink($editTable, $editUid, $label = 'Info', $options = [])
{
$image = Icons::getSpriteIcon('actions-document-info');
$class = array_key_exists('class', $options) ? htmlspecialchars($options['class']) : self::CSS_CLASS_BTN;
$class = ' class="'.$class.'"';
$label = isset($options['label']) ? $options['label'] : $label;
if (!TYPO3::isTYPO104OrHigher()) {
$image = Icons::getSpriteIcon('actions-document-info');
$class = array_key_exists('class', $options) ? htmlspecialchars($options['class']) : self::CSS_CLASS_BTN;
$class = ' class="'.$class.'"';
$label = isset($options['label']) ? $options['label'] : $label;

return '<a '.$class.' href="#" onclick="top.launchView('."'".$editTable."', ' ".$editUid."'); return false;".'">'.
$image.$label.'</a>';
}
$options[self::OPTION_ICON_NAME] = $options[self::OPTION_ICON_NAME] ?? 'actions-document-info';
$options[self::OPTION_DATA_ATTR] = [
'dispatch-action' => 'TYPO3.InfoWindow.showItem',
'dispatch-args-list' => sprintf('%s,%d', $editTable, $editUid),
];
$btn = $this->createModuleButton('#', $label, $options);

return '<a '.$class.' href="#" onclick="top.launchView('."'".$editTable."', ' ".$editUid."'); return false;".'">'.
$image.$label.'</a>';
return $btn->render();
}

/**
Expand All @@ -382,22 +391,21 @@ public function createInfoLink($editTable, $editUid, $label = 'Info', $options =
* @param string $editTable DB-Tabelle des Datensatzes
* @param int $recordUid UID des Datensatzes
* @param int $currentPid PID der aktuellen Seite des Datensatzes
* @param string $label Bezeichnung des Links
* @param string $label Bezeichnung des Links
*/
public function createMoveLink($editTable, $recordUid, $currentPid, $label = 'Move')
public function createMoveLink($editTable, $recordUid, $currentPid, $label = '')
{
$this->initClipboard();
$this->addBaseInlineJSCode();
$options = [];
$isSel = (string) $this->clipObj->isSelected($editTable, $recordUid);
$image = Icons::getSpriteIcon('actions-edit-cut'.($isSel ? '-release' : ''));
$options[self::OPTION_ICON_NAME] = 'actions-edit-cut'.($isSel ? '-release' : '');
$tooltip = $isSel ? 'paste' : 'cut';
$options[self::OPTION_HOVER_TEXT] = $this->getLanguageService()->sl('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:cm.'.$tooltip);

return '<a class="btn btn-default" href="#" onclick="'
.htmlspecialchars('return jumpSelf('.
Strings::quoteJSvalue(
$this->clipObj->selUrlDB($editTable, $recordUid, 0, 'cut' === $isSel, ['returnUrl' => ''])
).');')
.'" title="'.htmlspecialchars($GLOBALS['LANG']->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:cm.cut')).'">'
.$image.'</a>';
$uri = $this->clipObj->selUrlDB($editTable, $recordUid, 0, 'cut' === $isSel, ['returnUrl' => '']);
$btn = $this->createModuleButton($uri, $label, $options);

return $btn->render();
}

private function initClipboard()
Expand All @@ -423,22 +431,14 @@ private function initClipboard()
* @param int $uid
* @param int $moveId die uid des elements vor welches das element aus $uid gesetzt werden soll
* @param array $options
*
* @TODO use $this->createLinkForDataHandlerAction
*/
public function createMoveUpLink($table, $uid, $moveId, $options = [])
{
$jsCode = $this->getJavaScriptForLinkToDataHandlerAction('cmd['.$table.']['.$uid.'][move]=-'.$moveId.'&prErr=1&uPT=1', $options);
$label = isset($options['label']) ? $options['label'] : 'Move up';
$title = isset($options['title']) ? $options['title'] : $label;

$image = Icons::getSpriteIcon('actions-move-up');

return sprintf(
'<a onclick="%1$s" href="#">%2$s%3$s</a>',
$jsCode,
$image,
$label
return $this->createMoveUpDownLink(
'cmd['.$table.']['.$uid.'][move]=-'.$moveId.'&prErr=1&uPT=1',
'actions-move-up',
'Move up',
$options
);
}

Expand All @@ -449,46 +449,27 @@ public function createMoveUpLink($table, $uid, $moveId, $options = [])
* @param int $uid
* @param int $moveId die uid des elements nach welchem das element aus $uid gesetzt werden soll
* @param array $options
*
* @TODO use $this->createLinkForDataHandlerAction
*/
public function createMoveDownLink($table, $uid, $moveId, $options = [])
{
$jsCode = $this->getJavaScriptForLinkToDataHandlerAction('cmd['.$table.']['.$uid.'][move]=-'.$moveId, $options);
$label = isset($options['label']) ? $options['label'] : 'Move up';
$title = isset($options['title']) ? $options['title'] : $label;

$image = Icons::getSpriteIcon('actions-move-down');

return sprintf(
'<a onclick="%1$s" href="#">%2$s%3$s</a>',
$jsCode,
$image,
$label
return $this->createMoveUpDownLink(
'cmd['.$table.']['.$uid.'][move]=-'.$moveId,
'actions-move-down',
'Move down',
$options
);
}

/**
* Creates js code with command for TCE datahandler and redirect to current script.
* Simple example to delete a page record:
* $this->getJavaScriptForLinkToDataHandlerAction('cmd[pages][123][delete]=1').
*
* @param string $urlParameters command for datahandler
* @param array $options
*
* @return string
*/
protected function getJavaScriptForLinkToDataHandlerAction($urlParameters, array $options = [])
private function createMoveUpDownLink($cmd, $iconName, $defaultLabel, array $options)
{
$redirect = TYPO3::isTYPO115OrHigher() ? null : -1;
$jumpToUrl = BackendUtility::getLinkToDataHandlerAction('&'.$urlParameters, $redirect);
$label = isset($options['label']) ? $options['label'] : $defaultLabel;
if (isset($options['title']) && !isset($options[self::OPTION_HOVER_TEXT])) {
$options[self::OPTION_HOVER_TEXT] = $options['title'];
}

// the jumpUrl method is no longer global available since TYPO3 8.7
// furthermore we need the JS variable T3_THIS_LOCATION because it is used
// as redirect in getLinkToDataHandlerAction when -1 is passed
$this->addBaseInlineJSCode();
$options[self::OPTION_ICON_NAME] = $iconName;

return $this->getConfirmCode('return jumpToUrl('.Strings::quoteJSvalue($jumpToUrl).');', $options);
return $this->createLinkForDataHandlerAction($cmd, $label, $options);
}

/**
Expand Down Expand Up @@ -533,12 +514,12 @@ protected function getLinkThisScript($encode = true, array $options = [])
*/
public function createDeleteLink($table, $uid, $label = 'Remove', $options = [])
{
$image = Icons::getSpriteIcon('actions-delete');
$options['hover'] = 'Delete UID: '.$uid;
$options[self::OPTION_HOVER_TEXT] = 'Delete UID: '.$uid;
$options[self::OPTION_ICON_NAME] = 'actions-delete';

return $this->createLinkForDataHandlerAction(
'cmd['.$table.']['.$uid.'][delete]=1',
$image.$label,
$label,
$options
);
}
Expand Down Expand Up @@ -640,7 +621,19 @@ public function createModuleLink(array $params, $pid, $label, array $options = [
$params['id'] = $pid;
}
$uri = $this->getLinkThisScript(false, ['params' => $params]);
$recordButton = $this->createModuleButton($uri, $label, $options);

return $recordButton->render();
}

/**
* @param string $uri
* @param mixed $label
* @param array $options
* @return EnhancedLinkButton
*/
private function createModuleButton(string $uri, $label, array $options = [])
{
$recordButton = $this->makeLinkButton($uri, $label);

if (isset($options[self::OPTION_HOVER_TEXT])) {
Expand All @@ -652,15 +645,18 @@ public function createModuleLink(array $params, $pid, $label, array $options = [
}

$class = array_key_exists('class', $options) ? htmlspecialchars($options['class']) : '';

if (isset($options[self::OPTION_CONFIRM]) && strlen($options[self::OPTION_CONFIRM]) > 0) {
$class .= ' t3js-modal-trigger';
$recordButton->setDataAttributes(['content' => $options[self::OPTION_CONFIRM]]);
$recordButton->setOverrideCss(false);
}
$recordButton->setClasses($class);

return $recordButton->render();
if (isset($options[self::OPTION_DATA_ATTR])) {
$recordButton->addDataAttributes((array) $options[self::OPTION_DATA_ATTR]);
}

return $recordButton;
}

/**
Expand Down Expand Up @@ -1012,6 +1008,8 @@ public function getJSCode($pid, $location = '')
* and global Vars T3_RETURN_URL and T3_THIS_LOCATION to PageRenderer.
*
* @param string $location
*
* @deprecated should not be used anymore
*/
public function addBaseInlineJSCode($location = '')
{
Expand All @@ -1031,8 +1029,10 @@ public function addBaseInlineJSCode($location = '')
* @param string $location module url or empty
*
* @return string
*
* @deprecated should not be used anymore
*/
protected function getBaseJavaScriptCode($location = '')
private function getBaseJavaScriptCode($location = '')
{
$location = $location ? $location : $this->getLinkThisScript(false);

Expand Down Expand Up @@ -1237,6 +1237,8 @@ public function getTCEFormArray($table, $theUid, $isNew = false)
}

/**
* $this->createLinkForDataHandlerAction('cmd[pages][123][delete]=1').
*
* @param string $actionParameters
* @param string $label
* @param array $options
Expand All @@ -1245,23 +1247,20 @@ public function getTCEFormArray($table, $theUid, $isNew = false)
*/
public function createLinkForDataHandlerAction($actionParameters, $label, array $options = [])
{
// $options['sprite'] für abwärtskompatibilität
if (isset($options['icon']) || isset($options['sprite'])) {
$icon = isset($options['icon']) ? $options['icon'] : $options['sprite'];
$label = Icons::getSpriteIcon($icon, $options);
if (isset($options['sprite'])) {
$options[self::OPTION_ICON_NAME] = $options['sprite'];
}
$redirect = TYPO3::isTYPO115OrHigher() ? null : -1;
$uri = $this->buildDataHandlerUri($actionParameters, $redirect);

$jsCode = $this->getJavaScriptForLinkToDataHandlerAction($actionParameters, $options);
$title = '';
if (!empty($options['hover'])) {
$title = 'title="'.$options['hover'].'"';
}
$btn = $this->createModuleButton($uri, $label, $options);

$class = array_key_exists('class', $options) ? htmlspecialchars($options['class']) : self::CSS_CLASS_BTN;
$class = 'class="'.$class.'"';
return $btn->render();
}

return '<a href="#" '.$class.' onclick="'.htmlspecialchars($jsCode).'" '.
$title.'>'.$label.'</a>';
protected function buildDataHandlerUri(string $params, $redirect)
{
return BackendUtility::getLinkToDataHandlerAction('&'.$params, $redirect);
}

public function getLanguageService(): LanguageService
Expand Down
10 changes: 1 addition & 9 deletions Classes/Backend/Module/BaseModule.php
Original file line number Diff line number Diff line change
Expand Up @@ -503,16 +503,8 @@ protected function initDoc($doc)
$doc->inDocStylesArray[] = $doc->inDocStyles;
$doc->tableLayout = $this->getTableLayout();
$doc->setModuleTemplate($this->getModuleTemplate());
// Ernsthaft??
$doc->loadJavascriptLib('contrib/prototype/prototype.js');
// JavaScript
$doc->JScode .= '
<script>
script_ended = 0;
function jumpToUrl(URL) {
document.location = URL;
}
</script>
';

if (!TYPO3::isTYPO115OrHigher()) {
// TODO: Die Zeile könnte problematisch sein...
Expand Down
Loading

0 comments on commit c08035a

Please sign in to comment.