Skip to content

Commit f675fb4

Browse files
authored
Merge pull request #4 from KaririCode-Framework/develop
Enhance Sanitizer Component and README Updates
2 parents 35b0293 + 7f595b7 commit f675fb4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+3689
-703
lines changed

README.md

Lines changed: 135 additions & 121 deletions
Large diffs are not rendered by default.

README.pt-br.md

Lines changed: 184 additions & 169 deletions
Large diffs are not rendered by default.

composer.lock

Lines changed: 19 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Contract/SanitizationResult.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace KaririCode\Sanitizer\Contract;
6+
7+
interface SanitizationResult
8+
{
9+
public function addError(string $property, string $errorKey, string $message): void;
10+
11+
public function setSanitizedData(string $property, mixed $value): void;
12+
13+
public function hasErrors(): bool;
14+
15+
public function getErrors(): array;
16+
17+
public function getSanitizedData(): array;
18+
19+
public function toArray(): array;
20+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace KaririCode\Sanitizer\Contract;
6+
7+
use KaririCode\PropertyInspector\AttributeHandler;
8+
9+
interface SanitizationResultProcessor
10+
{
11+
/**
12+
* Processa os resultados de sanitização após a execução dos processadores.
13+
*
14+
* @param AttributeHandler $handler O manipulador que contém os atributos processados
15+
*
16+
* @return SanitizationResult O resultado da sanitização, incluindo dados processados e erros
17+
*/
18+
public function process(AttributeHandler $handler): SanitizationResult;
19+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace KaririCode\Sanitizer\Processor;
6+
7+
use KaririCode\PropertyInspector\AttributeHandler;
8+
use KaririCode\Sanitizer\Contract\SanitizationResult as SanitizationResultContract;
9+
use KaririCode\Sanitizer\Contract\SanitizationResultProcessor;
10+
use KaririCode\Sanitizer\SanitizationResult;
11+
12+
class DefaultSanitizationResultProcessor implements SanitizationResultProcessor
13+
{
14+
public function __construct(
15+
private SanitizationResultContract $result = new SanitizationResult()
16+
) {
17+
}
18+
19+
public function process(AttributeHandler $handler): SanitizationResult
20+
{
21+
$processedValues = $handler->getProcessedPropertyValues();
22+
$errors = $handler->getProcessingResultErrors();
23+
24+
foreach ($processedValues as $property => $data) {
25+
$this->result->setSanitizedData($property, $data['value']);
26+
27+
if (isset($errors[$property])) {
28+
$this->addPropertyErrors($this->result, $property, $errors[$property]);
29+
}
30+
}
31+
32+
return $this->result;
33+
}
34+
35+
private function addPropertyErrors(
36+
SanitizationResult $result,
37+
string $property,
38+
array $propertyErrors
39+
): void {
40+
foreach ($propertyErrors as $error) {
41+
$result->addError($property, $error['errorKey'], $error['message']);
42+
}
43+
}
44+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace KaririCode\Sanitizer\Processor\Domain\HtmlPurifier\Cleaner;
6+
7+
use KaririCode\Sanitizer\Processor\Domain\HtmlPurifier\Configuration;
8+
9+
final class AttributeCleaner
10+
{
11+
public function __construct(
12+
private readonly Configuration $config
13+
) {
14+
}
15+
16+
public function cleanAttributes(\DOMElement $element): void
17+
{
18+
if (!in_array(strtolower($element->tagName), $this->config->getAllowedTags(), true)) {
19+
return;
20+
}
21+
22+
$attributes = iterator_to_array($element->attributes);
23+
foreach ($attributes as $attr) {
24+
$attrName = $attr->name;
25+
$tagName = strtolower($element->tagName);
26+
27+
if (!$this->isAttributeAllowed($attrName, $tagName)) {
28+
$element->removeAttribute($attrName);
29+
}
30+
}
31+
}
32+
33+
private function isAttributeAllowed(string $attrName, string $tagName): bool
34+
{
35+
$allowedAttributes = $this->config->getAllowedAttributes();
36+
37+
return isset($allowedAttributes[$attrName])
38+
&& in_array($tagName, $allowedAttributes[$attrName], true);
39+
}
40+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace KaririCode\Sanitizer\Processor\Domain\HtmlPurifier\Cleaner;
6+
7+
final class InputCleaner
8+
{
9+
public function clean(string $input): string
10+
{
11+
// Remove scripts and inline events
12+
$input = preg_replace('/<script\b[^>]*>(.*?)<\/script>/is', '', $input);
13+
$input = preg_replace('/\bon\w+\s*=\s*"[^"]*"/i', '', $input);
14+
$input = preg_replace('/<!--.*?-->/s', '', $input);
15+
16+
return $input;
17+
}
18+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace KaririCode\Sanitizer\Processor\Domain\HtmlPurifier\Cleaner;
6+
7+
final class OutputCleaner
8+
{
9+
public function clean(string $output): string
10+
{
11+
// Remove any remaining HTML comments
12+
$output = preg_replace('/<!--.*?-->/s', '', $output);
13+
14+
// Normalize whitespace
15+
$output = preg_replace('/^\s+|\s+$/m', '', $output);
16+
$output = preg_replace('/\s+/', ' ', $output);
17+
18+
return trim($output);
19+
}
20+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace KaririCode\Sanitizer\Processor\Domain\HtmlPurifier;
6+
7+
final class Configuration
8+
{
9+
private const DEFAULT_ALLOWED_TAGS = [
10+
'p', 'br', 'strong', 'em', 'u', 'ol', 'ul', 'li',
11+
'a', 'img', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
12+
];
13+
private const DEFAULT_ALLOWED_ATTRIBUTES = [
14+
'href' => ['a'],
15+
'src' => ['img'],
16+
'alt' => ['img'],
17+
];
18+
19+
private array $allowedTags;
20+
private array $allowedAttributes;
21+
22+
public function __construct()
23+
{
24+
$this->allowedTags = self::DEFAULT_ALLOWED_TAGS;
25+
$this->allowedAttributes = self::DEFAULT_ALLOWED_ATTRIBUTES;
26+
}
27+
28+
public function configure(array $options): void
29+
{
30+
$this->allowedTags = $options['allowedTags'] ?? $this->allowedTags;
31+
$this->allowedAttributes = $options['allowedAttributes'] ?? $this->allowedAttributes;
32+
}
33+
34+
public function getAllowedTags(): array
35+
{
36+
return $this->allowedTags;
37+
}
38+
39+
public function getAllowedAttributes(): array
40+
{
41+
return $this->allowedAttributes;
42+
}
43+
}

0 commit comments

Comments
 (0)