first commit
This commit is contained in:
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/submission/Sanitizer.php
|
||||
*
|
||||
* Copyright (c) 2014-2020 Simon Fraser University
|
||||
* Copyright (c) 2000-2020 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class Sanitizer
|
||||
*
|
||||
* @brief A sanitization class to sanitize submission data before saving
|
||||
*/
|
||||
|
||||
namespace PKP\submission;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Support\Arr;
|
||||
use PKP\core\PKPString;
|
||||
|
||||
class Sanitizer
|
||||
{
|
||||
/**
|
||||
* Defined sanitization rule/method mapping to attributes
|
||||
* It's possible to have multiple sanitization rule for a single attributes
|
||||
*
|
||||
* $sanitizeMap = [
|
||||
* 'attribute_1' => 'class_method_1',
|
||||
* 'attribute_2' => ['class_method_21', 'class_method_22'],
|
||||
* ...
|
||||
* ]
|
||||
*/
|
||||
protected array $sanitizeMap = [];
|
||||
|
||||
/**
|
||||
* Passed params to sanitize
|
||||
*/
|
||||
protected array $sanitizeParams;
|
||||
|
||||
/**
|
||||
* Define if allow empty sanitization for attributes
|
||||
*/
|
||||
protected bool $allowEmptySanization = false;
|
||||
|
||||
/**
|
||||
* The entity code to number conversion to update
|
||||
* As TinyMCE do a force entity conversion even when defined the 'entity_encoding' as 'raw'
|
||||
*
|
||||
* @see 5.0+ : https://www.tiny.cloud/docs/configure/content-filtering/#entity_encoding
|
||||
* @see 6.0+ : https://www.tiny.cloud/docs/tinymce/6/content-filtering/#entity_encoding
|
||||
*/
|
||||
protected static array $entityCodeToCharMapping = [
|
||||
'&' => '&',
|
||||
'>' => '>',
|
||||
'<' => '<',
|
||||
'"' => '"',
|
||||
"'" => ''',
|
||||
];
|
||||
|
||||
/**
|
||||
* Convert the TinyMCE/HTMLPurify based converted entity codes to actual character
|
||||
*/
|
||||
public static function replaceSpecialCharEntityValueWithCharacter(string $string): string
|
||||
{
|
||||
return str_replace(
|
||||
array_values(static::$entityCodeToCharMapping),
|
||||
array_keys(static::$entityCodeToCharMapping),
|
||||
$string
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the sanitization process for given attribute
|
||||
*/
|
||||
protected function runSanitizationProcess(string $method, mixed $paramKey, mixed $beforeSanitizevalue): void
|
||||
{
|
||||
$this->sanitizeParams = array_merge($this->sanitizeParams, [
|
||||
$paramKey => $this->{$method}($beforeSanitizevalue),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize the submission localized/unlocalized title[title] attribute
|
||||
*/
|
||||
public function title(string|array $param): string|array
|
||||
{
|
||||
if (is_array($param)) {
|
||||
foreach ($param as $localeKey => $localizedSubmissionTitle) {
|
||||
// TinyMCE sometimes converts special chars to entity code and some times not
|
||||
// A very weird quirk by tinyMCE
|
||||
// e.g '&' turned into '&'
|
||||
$param[$localeKey] = self::replaceSpecialCharEntityValueWithCharacter(
|
||||
PKPString::stripUnsafeHtml($localizedSubmissionTitle, 'allowed_title_html')
|
||||
);
|
||||
}
|
||||
|
||||
return $param;
|
||||
}
|
||||
|
||||
return self::replaceSpecialCharEntityValueWithCharacter(
|
||||
PKPString::stripUnsafeHtml($param, 'allowed_title_html')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize the submission localized/unlocalized sub title[subtitle] attribute
|
||||
*/
|
||||
public function subtitle(string|array $param): string|array
|
||||
{
|
||||
return $this->title($param);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define should allow attributes with empty sanitization rules
|
||||
*/
|
||||
public function allowEmptySanitization(): self
|
||||
{
|
||||
$this->allowEmptySanization = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run sanitization
|
||||
*/
|
||||
public function sanitize(array $params, array $sanitizingKeys = []): array
|
||||
{
|
||||
$this->sanitizeParams = $params;
|
||||
|
||||
$sanitizableParams = empty($sanitizingKeys)
|
||||
? $params
|
||||
: array_intersect_key($params, array_flip($sanitizingKeys));
|
||||
|
||||
foreach ($sanitizableParams as $paramKey => $paramValue) {
|
||||
if (in_array($paramKey, $this->sanitizeMap)) {
|
||||
collect(Arr::wrap($this->sanitizeMap[$paramKey]))
|
||||
->each(
|
||||
fn ($method) => $this->runSanitizationProcess(
|
||||
$method,
|
||||
$paramKey,
|
||||
$paramValue
|
||||
)
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (method_exists($this, $paramKey)) {
|
||||
$this->runSanitizationProcess($paramKey, $paramKey, $paramValue);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$this->allowEmptySanization) {
|
||||
throw new Exception(
|
||||
sprintf("Running empty sanitization for attribute '%s' is now allowed", $paramKey)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->sanitizeParams;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user