easy_svg_sanitizer()
Liefert einen frischen SVG-Sanitizer, eingestellt wie die Uploads dieser Site, damit dein Add-on genau das behält und entfernt, was Easy SVG auch tut.
Funktion · Easy SVG · Status: Stabil
easy_svg_sanitizer() gibt deinem Plugin denselben SVG-Bereiniger, den Easy SVG für Uploads benutzt, mit den Erlaubnislisten und der Einstellung für fremde Verweise dieser Site. Nimm ihn immer dann, wenn dein Code SVG-Markup annimmt, das er nicht selbst geschrieben hat. Es ist die eine Funktion, die Easy SVG Add-ons dauerhaft zusagt.
Verwendung
easy_svg_sanitizer(): \enshrined\svgSanitize\Sanitizer|null
$sanitizer = easy_svg_sanitizer();
$clean = $sanitizer ? $sanitizer->sanitize( $markup ) : false;
Wann du es brauchst
- Dein Plugin lässt Benutzer SVG-Markup einfügen oder hochladen (ein Formularfeld, ein REST-Endpunkt, ein Block-Attribut), und du speicherst oder gibst es aus.
- Du importierst SVGs von anderswo, etwa aus einer fremden API, bevor du sie speicherst.
- Du baust eine Funktion auf Easy SVG auf und willst respektieren, was der Site-Betreiber über
esw_svg_allowed_tags,esw_svg_allowed_attributesundesw_svg_remove_remote_referenceserlaubt hat.
Lass es bleiben:
- Für Dateien, die über den WordPress-Uploader kommen. Die bereinigt Easy SVG schon, ein zweiter Durchlauf ändert nichts und kostet nur Zeit.
- Als Ersatz für die Klassen
esw_svg_tagsundesw_svg_attributesoder einen eigenennew \enshrined\svgSanitize\Sanitizer(). Das sind Interna, und ein anders gebauter Sanitizer ignoriert die Filter der Site. - Als einzige Prüfung für fremde Eingaben. Siehe „Was die Funktion nicht tut“ weiter unten.
Parameter
Diese Funktion hat keine Parameter.
Rückgabewert
Bei jedem Aufruf eine neue Sanitizer-Instanz, eingestellt für diese Site. null, wenn die Klasse \enshrined\svgSanitize\Sanitizer nicht existiert, also wenn der vendor-Ordner des Plugins fehlt.
Die Instanz gehört dir. Änderst du sie (zum Beispiel mit removeXMLTag( true )), betrifft das nichts anderes. Die Methoden, die du am häufigsten brauchst:
| Methode | Ergebnis |
|---|---|
sanitize( $markup ) | Bereinigtes Markup als String. '', wenn die Eingabe im Sinne von PHP leer ist ('' und '0'). false, wenn sich das XML nicht lesen lässt. Wirft eine LogicException, wenn das XML zwar lesbar ist, aber nicht genau eine svg-Wurzel hat, zum Beispiel bei einer HTML-Seite. |
getXmlIssues() | Was der letzte sanitize()-Aufruf entfernt hat, als array( array( 'message' => ..., 'line' => ... ) ). |
removeXMLTag( true ) | Lässt die ?xml-Deklaration weg, was du für die direkte Ausgabe im HTML willst. |
minify( true ) | Fasst Leerraum im Ergebnis zusammen. |
removeRemoteReferences( true ) | Macht deine Kopie strenger als die Site. |
Beispiele
Markup aus einem Formularfeld bereinigen
/**
* Vom Benutzer geliefertes SVG-Markup bereinigen, sonst '' zurückgeben.
*
* @param string $markup Rohes Markup.
* @return string
*/
function myplugin_clean_svg( $markup ) {
if ( ! function_exists( 'easy_svg_sanitizer' ) ) {
return '';
}
$sanitizer = easy_svg_sanitizer();
if ( null === $sanitizer ) {
return '';
}
$sanitizer->removeXMLTag( true );
try {
$clean = $sanitizer->sanitize( (string) $markup );
} catch ( \Throwable $e ) {
return '';
}
if ( ! is_string( $clean ) || '' === trim( $clean ) ) {
return '';
}
return $clean;
}
Behandle false, '' und eine Exception gleich: Die Eingabe war kein brauchbares SVG.
Ein SVG aus einer fremden API mit eigenen Grenzen importieren
/**
* Ein SVG abrufen, bereinigen und als Datei in uploads speichern.
*
* @param string $url Adresse des SVG.
* @return string|WP_Error Öffentliche URL der gespeicherten Datei.
*/
function myplugin_import_remote_svg( $url ) {
$max_bytes = 512 * KB_IN_BYTES;
$response = wp_safe_remote_get( $url, array( 'timeout' => 10, 'limit_response_size' => $max_bytes ) );
if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
return new WP_Error( 'myplugin_fetch', __( 'The SVG could not be downloaded.', 'myplugin' ) );
}
$markup = wp_remote_retrieve_body( $response );
if ( strlen( $markup ) >= $max_bytes || substr_count( strtolower( $markup ), '<use' ) > 200 ) {
return new WP_Error( 'myplugin_too_big', __( 'The SVG is too large or too complex.', 'myplugin' ) );
}
$sanitizer = function_exists( 'easy_svg_sanitizer' ) ? easy_svg_sanitizer() : null;
if ( null === $sanitizer ) {
return new WP_Error( 'myplugin_no_sanitizer', __( 'Easy SVG is not active.', 'myplugin' ) );
}
try {
$clean = $sanitizer->sanitize( $markup );
} catch ( \Throwable $e ) {
$clean = false;
}
if ( ! is_string( $clean ) || '' === trim( $clean ) ) {
return new WP_Error( 'myplugin_not_svg', __( 'This is not a usable SVG.', 'myplugin' ) );
}
$upload = wp_upload_bits( 'myplugin-' . md5( $url ) . '.svg', null, $clean );
if ( ! empty( $upload['error'] ) ) {
return new WP_Error( 'myplugin_write', $upload['error'] );
}
return $upload['url'];
}
// Ausgabe: ein img-Tag, escaped wie jede andere URL.
$src = myplugin_import_remote_svg( 'https://icons.example.com/logo.svg' );
if ( ! is_wp_error( $src ) ) {
printf( '<img src="%s" alt="%s" />', esc_url( $src ), esc_attr__( 'Logo', 'myplugin' ) );
}
Die Grenzen für Größe und use setzt du bewusst selbst: easy_svg_sanitizer() wendet die Upload-Grenzen der Site nicht an (siehe „Was die Funktion nicht tut“). Das Schreiben über wp_upload_bits() besteht auch die eigene Prüfung von Easy SVG auf diesem Weg, weil die Datei schon sauber ist. wp_upload_bits() akzeptiert den Namen .svg allerdings nur, wenn SVG auf der Site ein erlaubter Upload-Typ ist (der Schalter SVG-Uploads in der Mediathek erlauben) oder der aktuelle Benutzer unfiltered_upload hat.
Versionsprüfung und Protokoll der entfernten Teile
/**
* Markup bereinigen und protokollieren, was der Sanitizer entfernt hat.
*
* @param string $markup Rohes Markup.
* @return string Sauberes Markup oder ''.
*/
function myplugin_clean_and_report( $markup ) {
// EASY_SVG_API und easy_svg_sanitizer() kamen gemeinsam mit Easy SVG 5.0.0.
if ( ! defined( 'EASY_SVG_API' ) || EASY_SVG_API < 1 || ! function_exists( 'easy_svg_sanitizer' ) ) {
return '';
}
try {
$sanitizer = easy_svg_sanitizer();
$clean = $sanitizer ? $sanitizer->sanitize( $markup ) : false;
} catch ( \Throwable $e ) {
return '';
}
if ( $sanitizer && defined( 'WP_DEBUG_LOG' ) && WP_DEBUG_LOG ) {
foreach ( $sanitizer->getXmlIssues() as $issue ) {
error_log( sprintf( 'myplugin SVG: %s (line %d)', $issue['message'], $issue['line'] ) );
}
}
return is_string( $clean ) ? trim( $clean ) : '';
}
Das try umschließt auch den Aufruf von easy_svg_sanitizer(): Gibt ein Filter der Site für die Erlaubnislisten etwas anderes als ein Array zurück, wirft schon der Aufbau des Sanitizers einen TypeError.
Nimm diese Funktion, nicht die Klassen esw_svg_tags oder esw_svg_attributes und keinen selbst gebauten Sanitizer. Ein anders gebauter sieht die Filter der Site nicht: Er entfernt, was die Site behält, und, schlimmer, er behält, was die Site entfernt. Gib nie Markup aus, das nicht durch sanitize() gelaufen ist, und nie die rohe Eingabe, wenn sanitize() false geliefert oder geworfen hat.
So funktioniert es
- Easy SVG legt beim Laden einen globalen
$sanitizeran, aber nur, wenn die Klasse existiert und der Name noch frei ist. Er dient als Vorlage: Snippets aus Version 4.1 stellen ihn noch ein (etwa mitremoveXMLTag( true )), und diese Einstellungen gehen auf jede Kopie über. - Die Funktion klont diesen globalen Sanitizer, wenn darin ein echter
Sanitizersteckt, sonst fängt sie neu an. Liegt unter dem Namen etwas anderes (das Objekt eines anderen Plugins), wird es ignoriert und nicht aufgerufen. - Erlaubnislisten und Einstellung für fremde Verweise werden immer an der Kopie gesetzt. Sie gewinnen also gegen alles, was am globalen Objekt eingestellt ist.
- Eine Instanz pro Aufruf: Zwei Aufrufer teilen sich nie einen Zustand, und deine Änderungen an deiner Kopie wirken nirgends sonst.
Easy SVG nutzt diese Funktion selbst auf jedem Weg: Uploads und Sideloads (esw_svg_file_checker()), die Prüfung in wp_upload_bits (easy_svg_markup_is_clean()), die Prüfung jedes neuen Anhangs und die Icon-Bibliothek (anlegen, ersetzen und easy_svg_update_icon_markup()).
Was die Funktion nicht tut
Diese Schritte laufen in den Upload-Wegen von Easy SVG, rund um den Sanitizer, nicht in ihm. Wenn du fremde Eingaben verarbeitest, sorge selbst für etwas Gleichwertiges:
- Größengrenze. Uploads über der Einstellung Maximale SVG-Größe (MB) werden abgelehnt (Filter
easy_svg_max_bytes). - Komplexitätsgrenze. Dateien mit mehr als 10 PHP-Verarbeitungsanweisungen oder 1000
use-Elementen werden vor dem Parsen abgelehnt (Filtereasy_svg_max_php_tags,easy_svg_max_use_tags), weil solche Strukturen den Parser minutenlang beschäftigen können. - Leeres Ergebnis. Ein Ergebnis, das nach
trim()leer ist, wird abgelehnt. - Animationsprüfung. Hat eine Site
animateoderseterlaubt, entfernen Uploads zusätzlich Animationselemente, die aufhrefoderon*-Attribute zielen. - Icon-Härtung. Icons verlieren außerdem
script,style,foreignObject, jedes Animationselement, jedeson*-Attribut und jedeshref, das nicht mit#beginnt.
Stolperfallen
- Ruf sie spät genug auf. Die Funktion existiert, sobald die Hauptdatei von Easy SVG geladen ist. Auf oberster Ebene deiner eigenen Plugin-Datei gibt es sie unter Umständen noch nicht. Ruf sie in einem Hook auf (
initoder später) oder prüf dort mitfunction_exists(). nullist eine echte Antwort. Eine kaputte Installation ohnevendor-Ordner liefertnull. Ruf->sanitize()nie ungeprüft auf dem Rückgabewert auf.- Drei Arten zu scheitern.
false(nicht lesbar),''(leere Eingabe) und eineLogicException(nicht genau einesvg-Wurzel) heißen alle „nicht brauchbar“. Fang\Throwableab, nicht nurException. - Die Ausgabe ist eingerückt und beginnt mit einer XML-Deklaration. Ruf
removeXMLTag( true )auf, bevor du sie direkt ins HTML schreibst. - Eine veraltete Bibliothek kann gewinnen. Hat ein anderes Plugin zuerst eine ältere Version von enshrined/svg-sanitize geladen, bekommst du diese Klasse. Easy SVG zeigt Admins dann eine Warnung im Dashboard, auf der Plugin-Seite und in der Mediathek.
easy_svg_sanitizer()liefert trotzdem eine Instanz dieser älteren Klasse. - Sie bereinigt, sie prüft kein Design. Eine Datei, die ein nicht erlaubtes Element verliert, kommt trotzdem als gültiger String zurück. Mit
getXmlIssues()kannst du dem Benutzer sagen, was entfernt wurde.