esw_svg_allowed_tags
Filtert die SVG-Elemente, die Easy SVG beim Bereinigen behält: Lass ein fehlendes Zeichenelement zu oder entferne eines, das du nie speichern willst.
Filter · Easy SVG · Status: Stabil
Easy SVG bereinigt jedes SVG, bevor es gespeichert wird, und wirft jedes Element weg, dessen Name nicht auf einer Erlaubnisliste steht. Mit diesem Filter bekommst du diese Liste in die Hand: Du kannst ein Element ergänzen, das deine Grafiken brauchen, oder eines streichen, das du auf deiner Site nie haben willst. Die Änderung gilt für jeden Upload, jedes Icon und jedes Add-on der Site.
Verwendung
apply_filters( 'esw_svg_allowed_tags', array $tags )
add_filter( 'esw_svg_allowed_tags', 'myplugin_svg_tags' );
Wann du es brauchst
- Dein Design-Tool exportiert ein Element, das in der Standardliste fehlt, und es verschwindet beim Hochladen. Typisch ist ein Filter-Primitiv wie
feDropShadow, das die mitgelieferte Bibliothek nicht kennt. - Deine Site soll strenger sein als der Standard und ein Element aus jedem SVG entfernen, zum Beispiel eingebettete Bitmaps (
image). - Ein Add-on bereinigt Markup über
easy_svg_sanitizer()und soll dasselbe Element behalten wie deine Uploads. Das passiert automatisch, du musst nichts zusätzlich verdrahten.
Lass es bleiben:
- Wenn du Skripte oder eingebettetes HTML erlauben willst.
script,foreignObject,animate,setundiframebleiben draußen. Mehr dazu im Warnkasten unten. - Wenn nur eine einzelne Datei betroffen ist. Exportiere sie lieber ohne das Element neu, statt die Liste für die ganze Site zu erweitern.
- Wenn es eigentlich um ein Attribut geht. Attribute haben ihre eigene Liste, siehe
esw_svg_allowed_attributes.
Parameter
Rückgabewert
Die Elementnamen, die der Sanitizer behalten darf. Es muss ein Array sein. Alles andere (etwa null aus einem Callback, der sein return vergessen hat) lässt die Bibliothek beim Aufbau des Sanitizers einen TypeError werfen, und der Upload endet mit einem fatalen Fehler.
Standardwert
Die Liste AllowedTags aus enshrined/svg-sanitize 1.0.0, unverändert. Sie enthält bereits:
- HTML-Namen:
a,font,image,style - Formen und Struktur:
svg,g,defs,symbol,use,view,switch,path,rect,circle,ellipse,line,polyline,polygon,marker,mask,pattern,clippath - Text:
text,tspan,textpath,tref,title,desc,metadataund die alten SVG-Font-Elemente (glyph,hkern,vkern,altglyphund Verwandte) - Farbe und Effekte:
lineargradient,radialgradient,stop,filterund 23 Filter-Primitive vonfeBlendbisfeTurbulence - Animation:
animatecolor,animatemotion,animatetransform,mpath
Nicht auf der Liste und daher standardmäßig entfernt: script, foreignObject, animate, set, iframe, object, embed, feDropShadow, feImage und alles aus Editor-Namespaces wie sodipodi:namedview.
Beispiele
Ein fehlendes Filter-Primitiv erlauben
/**
* Schlagschatten aus feDropShadow behalten.
*
* @param string[] $tags Erlaubte Elementnamen.
* @return string[]
*/
function myplugin_allow_drop_shadow( $tags ) {
$tags[] = 'feDropShadow';
return $tags;
}
add_filter( 'esw_svg_allowed_tags', 'myplugin_allow_drop_shadow' );
Die Attribute, die feDropShadow braucht (dx, dy, stdDeviation, flood-color, flood-opacity), stehen schon auf der Attributliste, diese eine Zeile reicht also. Ohne sie bleibt das filter-Element leer stehen und der Schatten verschwindet stillschweigend.
Elemente entfernen, die deine Site nie will
/**
* Eingebettete Bitmaps und alte Font-Elemente aus jedem SVG entfernen.
*
* @param string[] $tags Erlaubte Elementnamen.
* @return string[]
*/
function myplugin_strict_svg_tags( $tags ) {
$blocked = array( 'image', 'font' );
return array_values(
array_filter(
$tags,
static function ( $tag ) use ( $blocked ) {
return ! in_array( strtolower( $tag ), $blocked, true );
}
)
);
}
add_filter( 'esw_svg_allowed_tags', 'myplugin_strict_svg_tags' );
Vergleiche in Kleinbuchstaben. Die Standardliste mischt Schreibweisen (feBlend, lineargradient), ein einfaches array_diff( $tags, array( 'feblend' ) ) findet daher nichts und entfernt nichts.
Defensive Variante für ein Plugin, das du weitergibst
/**
* Elemente nur einmal ergänzen und immer ein Array zurückgeben.
*
* @param mixed $tags Erlaubte Elementnamen.
* @return string[]
*/
function myplugin_svg_tags_defensive( $tags ) {
$tags = is_array( $tags ) ? $tags : array();
$known = array_map( 'strtolower', $tags );
foreach ( array( 'feDropShadow' ) as $tag ) {
if ( ! in_array( strtolower( $tag ), $known, true ) ) {
$tags[] = $tag;
}
}
return $tags;
}
// Nur einhängen, wenn Easy SVG die Liste auch liest.
if ( defined( 'EASY_SVG_API' ) || function_exists( 'easy_svg_sanitizer' ) ) {
add_filter( 'esw_svg_allowed_tags', 'myplugin_svg_tags_defensive' );
}
Ohne Bedingung einzuhängen schadet auch nicht: Ohne Easy SVG wendet niemand den Filter an. Die Abfrage dokumentiert nur die Absicht. Kann dein Plugin vor Easy SVG geladen werden, gehört die Abfrage in einen Callback auf plugins_loaded, denn beim Laden deiner Datei hat Easy SVG noch nichts definiert.
Füge niemals script, foreignObject, animate, set oder iframe hinzu. Die Erlaubnisliste entscheidet nur, welche Namen vorkommen dürfen. Was ein Element tut, prüft sie nicht: Ein animate-Element kann über attributeName und values ein href auf javascript: setzen, und foreignObject bettet HTML ein, für das die SVG-Regeln nie gedacht waren. Deine Admins öffnen hochgeladene Dateien in der Mediathek, eine aufgeweichte Liste ist also ein Weg, Code in ihrem Browser auszuführen.
So funktioniert es
Der Filter wird in esw_svg_tags::getTags() angewendet (easy-svg.php, Zeile 74). easy_svg_sanitizer() baut bei jedem Aufruf einen neuen Sanitizer und übergibt new esw_svg_tags() an setAllowedTags(). Das ruft getTags() auf, schreibt jeden Eintrag klein und speichert das Ergebnis. Dein Callback läuft also einmal pro Sanitizer, und jeder Weg, der SVG bereinigt, baut sich seinen eigenen:
Beim Bereinigen läuft die Bibliothek durch das Dokument und entfernt jedes Element, dessen kleingeschriebener Name nicht auf der Liste steht, samt allem, was darin liegt. Danach prüft sie die Attribute gegen esw_svg_allowed_attributes.
Was danach passiert, hängt vom Weg ab:
- Uploads und neue Anhänge: Nach dem Bereinigen sucht
esw_svg_file_checker()nach Animationselementen. Lässt deine Listeanimate,setoderanimate*durch, entfernteasy_svg_neutralize_href_animation()die, derenattributeNameaufhrefoder einenon*-Handler zielt. Das passiert nur auf den Datei-Wegen, nicht ineasy_svg_sanitizer(). - wp_upload_bits (XML-RPC und Plugins, die Bytes schreiben): Der Filter kann Bytes nicht umschreiben, also wird die Datei abgelehnt, sobald der Sanitizer etwas ändern würde. Streichst du ein Element, das in einer Datei vorkommt, scheitert dieser Upload auf diesem Weg.
- Icons: Nach dem Bereinigen entfernt
easy_svg_harden_icon_markup()die Elemente ausEASY_SVG_ICON_UNSAFE_ELEMENTS(darunterstyle,script,foreignobjectund jedes Animationselement), egal was deine Liste sagt, weil Icons direkt in die Seite eingebettet werden.
Die Upload-Filter sind nur registriert, solange SVG-Uploads in der Mediathek erlauben unter Icons, Einstellungen eingeschaltet ist. Die Prüfung neuer Anhänge läuft immer.
Stolperfallen
- Ein entferntes Element nimmt seine Kinder mit. Streichst du
godera, verschwindet jede Form in einer Gruppe oder einem Link, oft die ganze Zeichnung. - Gib immer ein Array zurück. Ein Callback, der
nulloder einen String liefert, führt beim Upload zu einem fatalen Fehler, nicht zu einem stillen Rückfall. - Vergleich ohne, Entfernen mit Groß- und Kleinschreibung. Abgeglichen wird kleingeschrieben, dein eigenes
array_diff()unterscheidet aber. Vergleiche mitstrtolower(). - Präfixe zählen mit. Schreibt eine Datei
svg:rect, musssvg:rectauf der Liste stehen. Eine Datei mitsvg:svgals Wurzel kommt ohne Zeichnung heraus. - Das Readme-Beispiel bewirkt nichts.
viewsteht schon auf der Standardliste. - Alte Dateien werden nicht neu geprüft. Die Liste greift, wenn eine Datei ankommt. Was schon in der Mediathek liegt, behält, was die Liste damals erlaubt hat.
- Der alte globale Sanitizer ändert die Liste nicht.
setAllowedTags()am alten globalen$sanitizerwirkt nicht, weileasy_svg_sanitizer()die Liste an seiner Kopie neu setzt. Nimm diesen Filter. - Kein Kontext-Argument. Der Callback bekommt nur die Liste. Uploads per WP-CLI, Cron oder Importer laufen unter Umständen ohne angemeldeten Benutzer. Machst du die Liste von
current_user_can()abhängig, sehen diese Wege eine andere Liste.