Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
46 lines
2.1 KiB
PHP
46 lines
2.1 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace LIT\MCP\Abilities;
|
||
|
||
defined('ABSPATH') || exit;
|
||
|
||
/**
|
||
* Divi markup in raw content (security audit M1, ruling S52): the single check for every path
|
||
* that stores client text as post_content without the Divi pipeline (lit/content-create and
|
||
* lit/content-update `content`, lit/media-update `description`). Such content would bypass the
|
||
* builder-only gates of the Divi tools (rulings S7/S26).
|
||
*
|
||
* Checked is the form storage will see: kses (wp_kses_no_null) removes C0 control characters and
|
||
* "\0" sequences only AFTER any check on the raw value, so a NUL inside "<!-- wp:divi/" would
|
||
* otherwise hide a real block. normalized() applies those removals plus DEL (like
|
||
* Divi\Compose\ControlChars::strip()); contains() refuses when either the raw or the normalized
|
||
* form holds a delimiter WordPress' block parser accepts for divi/* blocks ("<!--", whitespace,
|
||
* optional "/", lower-case "wp:divi/" – Divi's BlockParser extends it) or a Divi 4 shortcode.
|
||
* Other block markup stays allowed and goes through WordPress' kses. Pure PHP.
|
||
*
|
||
* Stays in Abilities although it knows Divi's markup: it only recognizes text patterns (no Divi class, no import,
|
||
* CoreIndependenceTest), and every writer of client text – Divi or not – needs the same check.
|
||
*/
|
||
final class DiviMarkup
|
||
{
|
||
private const PATTERN = '~<!--\s+/?wp:divi/|\[/?et_pb_~';
|
||
|
||
public const HINT = 'Divi-Inhalte über `divi` (lit-content-create) bzw. die lit-divi-*-Tools '
|
||
. '(lit-divi-insert, lit-divi-update, lit-divi-move, lit-divi-delete) ändern.';
|
||
|
||
public static function contains(string $content): bool
|
||
{
|
||
return preg_match(self::PATTERN, $content) === 1 || preg_match(self::PATTERN, self::normalized($content)) === 1;
|
||
}
|
||
|
||
/** $content without what kses (wp_kses_no_null) and ControlChars remove before it is stored. */
|
||
public static function normalized(string $content): string
|
||
{
|
||
$content = (string) preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/', '', $content);
|
||
|
||
return (string) preg_replace('/\\\\+0+/', '', $content);
|
||
}
|
||
}
|