Skip to content

Commit

Permalink
Merge branch '11.0' into 11.x
Browse files Browse the repository at this point in the history
# Conflicts:
#	doc/03_Documents/01_Editables/40_WYSIWYG.md
#	models/DataObject/ClassDefinition/Data/Select.php
#	models/Translation/Dao.php
#	tests/Model/DataObject/ObjectTest.php
  • Loading branch information
dvesh3 committed Oct 16, 2023
2 parents d25b5f5 + dbd23f5 commit b4ec3ba
Show file tree
Hide file tree
Showing 11 changed files with 81 additions and 61 deletions.
3 changes: 3 additions & 0 deletions doc/03_Documents/01_Editables/40_WYSIWYG.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,6 @@ framework:
ol: ['class', 'style']
```
If you want to adapt this configuration please have a look at the [symfony documentation](https://symfony.com/doc/current/html_sanitizer.html). Add your custom configuration to you project, e.g. to `config/packages/html_sanitizer.yaml`

> Note: When using API to set WYSIWYG data, please pass encoded characters for html entities e.g. <,>, & etc.
> The data is encoded by the sanitizer before persisting into db and the same encoded data will be returned by the API.
4 changes: 3 additions & 1 deletion doc/23_Installation_and_Upgrade/09_Upgrade_Notes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,9 @@
#### [Security] :

- Enabled Content Security Policy by default.
- Implemented Symfony HTML sanitizer for WYSIWYG editors.
- Implemented Symfony HTML sanitizer for WYSIWYG editors. Please make sure to sanitize your persisted data with help of this [script](https://gist.github.com/dvesh3/0e585a16dfbf546bc17a9eef1c5640b3).
Also, when using API to set WYSIWYG data, please pass encoded characters for html entities <,>, & etc.
The data is encoded by the sanitizer before persisting into db and the same encoded data will be returned by the API.


-----------------
Expand Down
4 changes: 3 additions & 1 deletion lib/HttpKernel/CacheWarmer/PimcoreCoreCacheWarmer.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ private function getClassesFromDirectory(string $dir, string $excludePattern, st
$className = preg_replace('@\.php$@', '', $className);
$className = str_replace(DIRECTORY_SEPARATOR, '\\', $className);

if (class_exists($className)) {
// include classes, interfaces and traits
// exclude invalid files like helper-functions
if (!preg_match('/[_.-]/', $className)) {
$classes[] = $className;
}
}
Expand Down
2 changes: 1 addition & 1 deletion models/Asset.php
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ public static function create(int $parentId, array $data = [], bool $save = true
$asset->save();
}

if ($tmpFile) {
if (file_exists($tmpFile)) {
unlink($tmpFile);
}

Expand Down
2 changes: 1 addition & 1 deletion models/DataObject/ClassDefinition/Data/ExternalImage.php
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ public function getVersionPreview(mixed $data, DataObject\Concrete $object = nul
return '<img style="max-width:200px;max-height:200px" src="' . $data->getUrl() . '" /><br><a href="' . $data->getUrl() . '">' . $data->getUrl() . '</>';
}

return $data;
return '';
}

public function getForCsvExport(DataObject\Localizedfield|DataObject\Fieldcollection\Data\AbstractData|DataObject\Objectbrick\Data\AbstractData|DataObject\Concrete $object, array $params = []): string
Expand Down
2 changes: 1 addition & 1 deletion models/DataObject/ClassDefinition/Data/Select.php
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ public function enrichLayoutDefinition(?Concrete $object, array $context = []):
* @param DataObject\Concrete|null $object
*
*/
public function getDataForGrid(?string $data, Concrete $object = null, array $params = []): array|string|null
public function getDataForGrid(mixed $data, Concrete $object = null, array $params = []): array|string|int|null
{
$optionsProvider = DataObject\ClassDefinition\Helper\OptionsProviderResolver::resolveProvider(
$this->getOptionsProviderClass(),
Expand Down
12 changes: 6 additions & 6 deletions models/DataObject/ClassDefinition/Data/Wysiwyg.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ public function setMaxCharacters(int|string $maxCharacters): void
*/
public function getDataForResource(mixed $data, DataObject\Concrete $object = null, array $params = []): ?string
{
if (is_string($data) && ($params['sanitize'] ?? true)) {
$data = self::getWysiwygSanitizer()->sanitizeFor('body', $data);
}

return Text::wysiwygText($data);
}

Expand All @@ -104,10 +108,6 @@ public function getDataForResource(mixed $data, DataObject\Concrete $object = nu
*/
public function getDataFromResource(mixed $data, DataObject\Concrete $object = null, array $params = []): ?string
{
if (is_string($data)) {
$data = html_entity_decode(self::getWysiwygSanitizer()->sanitizeFor('body', $data));
}

return Text::wysiwygText($data);
}

Expand All @@ -118,7 +118,7 @@ public function getDataFromResource(mixed $data, DataObject\Concrete $object = n
*/
public function getDataForQueryResource(mixed $data, DataObject\Concrete $object = null, array $params = []): ?string
{
$data = $this->getDataForResource($data, $object, $params);
$data = $this->getDataForResource($data, $object, array_merge($params, ['sanitize' => false]));

if (null !== $data) {
$data = strip_tags($data, '<a><img>');
Expand Down Expand Up @@ -149,7 +149,7 @@ public function getDataForSearchIndex(DataObject\Localizedfield|DataObject\Field
*/
public function getDataForEditmode(mixed $data, DataObject\Concrete $object = null, array $params = []): ?string
{
return $this->getDataForResource($data, $object, $params);
return $this->getDataForResource($data, $object, array_merge($params, ['sanitize' => false]));
}

/**
Expand Down
13 changes: 9 additions & 4 deletions models/Document/Editable/Wysiwyg.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,14 @@ public function frontend()

public function setDataFromResource(mixed $data): static
{
$helper = self::getWysiwygSanitizer();
$this->text = html_entity_decode($helper->sanitizeFor('body', $data));
$this->text = $data;

return $this;
}

public function setDataFromEditmode(mixed $data): static
{
$helper = self::getWysiwygSanitizer();
$this->text = html_entity_decode($helper->sanitizeFor('body', $data));
$this->text = $data;

return $this;
}
Expand Down Expand Up @@ -129,4 +127,11 @@ public function rewriteIds(array $idMapping): void
$html->clear();
unset($html);
}

public function save(): void
{
$helper = self::getWysiwygSanitizer();
$this->text = $helper->sanitizeFor('body', $this->text);
$this->getDao()->save();
}
}
7 changes: 6 additions & 1 deletion models/Translation/Dao.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,16 @@ public function save(): void
continue;
}

if ($text != strip_tags($text)) {
$text = $sanitizer->sanitizeFor('body', $text);
$this->model->addTranslation($language, $text);
}

$data = [
'key' => $this->model->getKey(),
'type' => $this->model->getType(),
'language' => $language,
'text' => html_entity_decode($sanitizer->sanitizeFor('body', $text)),
'text' => $text,
'modificationDate' => $this->model->getModificationDate(),
'creationDate' => $this->model->getCreationDate(),
'userOwner' => $this->model->getUserOwner(),
Expand Down
44 changes: 22 additions & 22 deletions tests/Model/DataObject/ObjectTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -355,28 +355,28 @@ public function testEmptyValuesAsNullBackend(): void
$this->assertNull($value);
}

// public function testSanitization(): void
// {
// $db = Db::get();
//
// $object = TestHelper::createEmptyObject();
// $object->setWysiwyg('!@#$%^abc\'"<script>console.log("ops");</script> 测试< edf > "');
// $object->save();
//
// //reload from db
// $object = DataObject::getById($object->getId(), ['force' => true]);
//
// $this->assertEquals('!@#$%^abc\'" 测试< edf > "', $object->getWysiwyg(), 'Asseting setter/getter value is sanitized');
//
// $dbQueryValue = $db->fetchOne(
// sprintf(
// 'SELECT `wysiwyg` FROM object_query_%s WHERE oo_id = %d',
// $object->getClassName(),
// $object->getId()
// )
// );
// $this->assertEquals('!@#$%^abc\'" 测试< edf > "', $dbQueryValue, 'Asserting object_query table value is persisted as sanitized');
// }
public function testSanitization(): void
{
$db = Db::get();

$object = TestHelper::createEmptyObject();
$object->setWysiwyg('!@#$%^abc\'"<script>console.log("ops");</script> 测试&lt; edf &gt; "');
$object->save();

//reload from db
$object = DataObject::getById($object->getId(), ['force' => true]);

$this->assertEquals('!@#$%^abc\'" 测试< edf > "', html_entity_decode($object->getWysiwyg()), 'Asseting setter/getter value is sanitized');

$dbQueryValue = $db->fetchOne(
sprintf(
'SELECT `wysiwyg` FROM object_query_%s WHERE oo_id = %d',
$object->getClassName(),
$object->getId()
)
);
$this->assertEquals('!@#$%^abc\'" 测试< edf > "', html_entity_decode($dbQueryValue), 'Asserting object_query table value is persisted as sanitized');
}

public function testInputCheckValidate(): void
{
Expand Down
49 changes: 26 additions & 23 deletions tests/Unit/Translation/TranslatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

namespace Pimcore\Tests\Unit\Translation;

use Pimcore\Cache\RuntimeCache;
use Pimcore\Db;
use Pimcore\Model\Translation;
use Pimcore\Tests\Support\Test\TestCase;
Expand Down Expand Up @@ -243,27 +244,29 @@ public function testCacheGetsInvalidatedOnSave(): void
$this->assertCount(count($beforeAdd) + 1, $afterAdd);
}

// public function testSanitizedTranslation(): void
// {
// $translation = new Translation();
// $key = 'sanitizerTest';
// $translation->setDomain('messages');
// $translation->setKey($key);
// $translation->setTranslations(['en' => '!@#$%^abc\'"<script>console.log("ops");</script> 测试< edf > "']);
// $translation->save();
//
// $translation = Translation::getByKey($key);
// $getter = $translation->getTranslation('en');
// $this->assertEquals('!@#$%^abc\'" 测试< edf > "', $getter, 'Asserting translation is properly sanitized');
//
// $db = Db::get();
// $dbValue = $db->fetchOne(
// sprintf(
// 'SELECT `text` FROM translations_messages WHERE `key` = %s AND `language` = %s',
// $db->quote($key),
// $db->quote('en')
// )
// );
// $this->assertEquals('!@#$%^abc\'" 测试< edf > "', $dbValue, 'Asserting translation is persisted as sanitized');
// }
public function testSanitizedTranslation(): void
{
$translation = new Translation();
$key = 'sanitizerTest';
$translation->setDomain('messages');
$translation->setKey($key);
$translation->setTranslations(['en' => '!@#$%^abc\'"<script>console.log("ops");</script> 测试&lt; edf &gt; "']);
$translation->save();

RuntimeCache::clear();

$translation = Translation::getByKey($key);
$getter = $translation->getTranslation('en');
$this->assertEquals('!@#$%^abc\'" 测试< edf > "', html_entity_decode($getter), 'Asserting translation is properly sanitized');

$db = Db::get();
$dbValue = $db->fetchOne(
sprintf(
'SELECT `text` FROM translations_messages WHERE `key` = %s AND `language` = %s',
$db->quote($key),
$db->quote('en')
)
);
$this->assertEquals('!@#$%^abc\'" 测试< edf > "', html_entity_decode($dbValue), 'Asserting translation is persisted as sanitized');
}
}

0 comments on commit b4ec3ba

Please sign in to comment.