diff --git a/bundles/AdminBundle/Controller/Admin/DataObject/ClassificationstoreController.php b/bundles/AdminBundle/Controller/Admin/DataObject/ClassificationstoreController.php index 6d29374d8a8..597650e003c 100644 --- a/bundles/AdminBundle/Controller/Admin/DataObject/ClassificationstoreController.php +++ b/bundles/AdminBundle/Controller/Admin/DataObject/ClassificationstoreController.php @@ -128,7 +128,7 @@ public function deleteGroupAction(Request $request): JsonResponse */ public function createGroupAction(Request $request): JsonResponse { - $name = SecurityHelper::getStringWithoutControlChars($request->get('name')); + $name = SecurityHelper::convertHtmlSpecialChars($request->get('name')); $storeId = $request->get('storeId'); $config = Classificationstore\GroupConfig::getByName($name, $storeId); @@ -155,7 +155,7 @@ public function createGroupAction(Request $request): JsonResponse */ public function createStoreAction(Request $request): JsonResponse { - $name = SecurityHelper::getStringWithoutControlChars($request->get('name')); + $name = SecurityHelper::convertHtmlSpecialChars($request->get('name')); $config = Classificationstore\StoreConfig::getByName($name); @@ -181,7 +181,7 @@ public function createStoreAction(Request $request): JsonResponse */ public function createCollectionAction(Request $request): JsonResponse { - $name = SecurityHelper::getStringWithoutControlChars($request->get('name')); + $name = SecurityHelper::convertHtmlSpecialChars($request->get('name')); $storeId = $request->get('storeId'); $config = Classificationstore\CollectionConfig::getByName($name, $storeId); diff --git a/bundles/AdminBundle/Resources/public/js/pimcore/helpers.js b/bundles/AdminBundle/Resources/public/js/pimcore/helpers.js index 63778fd39d9..c77adc32300 100644 --- a/bundles/AdminBundle/Resources/public/js/pimcore/helpers.js +++ b/bundles/AdminBundle/Resources/public/js/pimcore/helpers.js @@ -22,6 +22,17 @@ pimcore.helpers.sanitizeUrlSlug = function (slug) { return slug.replace(/[^a-z0-9-_+/]/gi, ''); }; +pimcore.helpers.htmlEncodeTextField = function (textField) { + if(textField.getValue()) { + textField.suspendEvent('change'); + const decodedValue = Ext.util.Format.htmlDecode(textField.getValue()); + textField.setValue( + Ext.util.Format.htmlEncode(decodedValue) + ); + textField.resumeEvent('change'); + } +}; + pimcore.helpers.registerKeyBindings = function (bindEl, ExtJS) { if (!ExtJS) { diff --git a/bundles/AdminBundle/Resources/public/js/pimcore/settings/staticroutes.js b/bundles/AdminBundle/Resources/public/js/pimcore/settings/staticroutes.js index 3dcbbbb99cd..8feda63cc64 100644 --- a/bundles/AdminBundle/Resources/public/js/pimcore/settings/staticroutes.js +++ b/bundles/AdminBundle/Resources/public/js/pimcore/settings/staticroutes.js @@ -96,11 +96,11 @@ pimcore.settings.staticroutes = Class.create({ var typesColumns = [ {text:t("name"), flex:50, sortable:true, dataIndex:'name', - editor:new Ext.form.TextField({})}, + editor:new Ext.form.TextField({listeners: {'change': pimcore.helpers.htmlEncodeTextField}})}, {text:t("pattern"), flex:100, sortable:true, dataIndex:'pattern', - editor:new Ext.form.TextField({})}, + editor:new Ext.form.TextField({listeners: {'change': pimcore.helpers.htmlEncodeTextField}})}, {text:t("reverse"), flex:100, sortable:true, dataIndex:'reverse', - editor:new Ext.form.TextField({})}, + editor:new Ext.form.TextField({listeners: {'change': pimcore.helpers.htmlEncodeTextField}})}, {text:t("controller"), flex:200, sortable:false, dataIndex:'controller', editor:new Ext.form.ComboBox({ store:new Ext.data.JsonStore({ @@ -127,14 +127,17 @@ pimcore.settings.staticroutes = Class.create({ valueField:'name', listConfig: { maxWidth: 400 + }, + listeners: { + 'change': pimcore.helpers.htmlEncodeTextField } })}, {text:t("variables"), flex:50, sortable:false, dataIndex:'variables', - editor:new Ext.form.TextField({})}, + editor:new Ext.form.TextField({listeners: {'change': pimcore.helpers.htmlEncodeTextField}})}, {text:t("defaults"), flex:50, sortable:false, dataIndex:'defaults', - editor:new Ext.form.TextField({})}, + editor:new Ext.form.TextField({listeners: {'change': pimcore.helpers.htmlEncodeTextField}})}, {text:t("site_ids"), flex:100, sortable:true, dataIndex:"siteId", - editor:new Ext.form.TextField({}), + editor:new Ext.form.TextField({listeners: {'change': pimcore.helpers.htmlEncodeTextField}}), tooltip: t("site_ids_tooltip") }, {text:t("priority"), flex:50, sortable:true, dataIndex:'priority', editor:new Ext.form.ComboBox({ @@ -143,7 +146,7 @@ pimcore.settings.staticroutes = Class.create({ triggerAction:"all" })}, {text:t("methods"), flex:50, sortable:false, dataIndex:'methods', - editor:new Ext.form.TextField({}), + editor:new Ext.form.TextField({listeners: {'change': pimcore.helpers.htmlEncodeTextField}}), }, {text: t("creationDate"), sortable: true, dataIndex: 'creationDate', editable: false, hidden: true, @@ -186,9 +189,15 @@ pimcore.settings.staticroutes = Class.create({ return; } - pimcore.helpers.deleteConfirm(t('staticroute'), data.data.name, function () { - grid.getStore().removeAt(rowIndex); - }.bind(this)); + const decodedName = Ext.util.Format.htmlDecode(data.data.name); + + pimcore.helpers.deleteConfirm( + t('staticroute'), + Ext.util.Format.htmlEncode(decodedName), + function () { + grid.getStore().removeAt(rowIndex); + }.bind(this) + ); }.bind(this) }] } diff --git a/lib/Security/SecurityHelper.php b/lib/Security/SecurityHelper.php index 0bfd3a42b70..e81d04d7e05 100644 --- a/lib/Security/SecurityHelper.php +++ b/lib/Security/SecurityHelper.php @@ -17,8 +17,12 @@ class SecurityHelper { - public static function getStringWithoutControlChars(string $text): string + public static function convertHtmlSpecialChars(?string $text): ?string { - return preg_replace('[\\\\<>"\'`!?/%$(){};,:|=]', '', $text); + if(is_string($text)){ + return htmlspecialchars($text, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8', false); + } + + return null; } } diff --git a/models/Staticroute.php b/models/Staticroute.php index 983379b303a..2e4dcc65526 100644 --- a/models/Staticroute.php +++ b/models/Staticroute.php @@ -17,6 +17,7 @@ use Pimcore\Event\FrontendEvents; use Pimcore\Model\Exception\NotFoundException; +use Pimcore\Security\SecurityHelper; use Symfony\Component\EventDispatcher\GenericEvent; /** @@ -292,7 +293,7 @@ public function setId($id) */ public function setPattern($pattern) { - $this->pattern = $pattern; + $this->pattern = SecurityHelper::convertHtmlSpecialChars($pattern); return $this; } @@ -304,7 +305,7 @@ public function setPattern($pattern) */ public function setController($controller) { - $this->controller = $controller; + $this->controller = SecurityHelper::convertHtmlSpecialChars($controller); return $this; } @@ -316,7 +317,7 @@ public function setController($controller) */ public function setVariables($variables) { - $this->variables = $variables; + $this->variables = SecurityHelper::convertHtmlSpecialChars($variables); return $this; } @@ -328,7 +329,7 @@ public function setVariables($variables) */ public function setDefaults($defaults) { - $this->defaults = $defaults; + $this->defaults = SecurityHelper::convertHtmlSpecialChars($defaults); return $this; } @@ -360,7 +361,7 @@ public function getPriority() */ public function setName($name) { - $this->name = $name; + $this->name = SecurityHelper::convertHtmlSpecialChars($name); return $this; } @@ -380,7 +381,7 @@ public function getName() */ public function setReverse($reverse) { - $this->reverse = $reverse; + $this->reverse = SecurityHelper::convertHtmlSpecialChars($reverse); return $this; } @@ -611,7 +612,9 @@ public function setMethods($methods) { if (is_string($methods)) { $methods = strlen($methods) ? explode(',', $methods) : []; - $methods = array_map('trim', $methods); + foreach($methods as $key => $method) { + $methods[$key] = SecurityHelper::convertHtmlSpecialChars(trim($method)); + } } $this->methods = $methods;