19declare(strict_types=1);
27use ILIAS\FileUpload\Processor\IsMimeTypeOrExtension;
34 use IsMimeTypeOrExtension;
40 private const SVG =
'svg';
53 "onbegin",
"onend",
"onrepeat",
"onabort",
"onerror",
"onresize",
"onscroll",
"onunload",
54 "oncancel",
"oncanplay",
"oncanplaythrough",
"onchange",
"onclick",
"onclose",
55 "oncuechange",
"ondblclick",
"ondrag",
"ondragend",
"ondragenter",
"ondragleave",
56 "ondragover",
"ondragstart",
"ondrop",
"ondurationchange",
"onemptied",
"onended",
57 "onfocus",
"oninput",
"oninvalid",
"onkeydown",
"onkeypress",
"onkeyup",
"onload",
58 "onloadeddata",
"onloadedmetadata",
"onloadstart",
"onmousedown",
"onmouseenter",
59 "onmouseleave",
"onmousemove",
"onmouseout",
"onmouseover",
"onmouseup",
"onmousewheel",
60 "onpause",
"onplay",
"onplaying",
"onprogress",
"onratechange",
"onreset",
"onresize",
61 "onscroll",
"onseeked",
"onseeking",
"onselect",
"onshow",
"onstalled",
"onsubmit",
62 "onsuspend",
"ontimeupdate",
"ontoggle",
"onvolumechange",
"onwaiting",
63 "onactivate",
"onfocusin",
"onfocusout",
68 ?
string $additional_message_script =
null,
69 ?
string $additional_message_base64 =
null,
70 ?
string $additional_message_foreign_object =
null,
71 ?
string $additional_message_elements =
null
74 $this->rejection_message_script = $additional_message_script ??
'contains script tags';
75 $this->rejection_message_base64 = $additional_message_base64 ??
'contains base64 encoded content';
76 $this->rejection_message_foreign_object = $additional_message_foreign_object ??
'contains foreign object';
77 $this->rejection_message_elements = $additional_message_elements ??
'contains not allowed or unknown elements or attributes';
82 return $this->isMimeTypeOrExtension($metadata, self::SVG, [self::SVG_MIME_TYPE]);
95 $dom = new \DOMDocument();
97 $dom->loadXML($raw_svg_content, LIBXML_NOWARNING | LIBXML_NOERROR);
98 }
catch (\Exception) {
101 $errors = libxml_get_errors();
102 if ($errors !== []) {
110 $raw_svg_content = (string) $stream;
111 if ($raw_svg_content ===
false) {
122 $prohibited_attributes = fn(
string $name):
bool => in_array(strtolower($name), $this->svg_event_lists,
true);
123 return $looper($dom, $prohibited_attributes) !==
false;
128 if (preg_match(self::REGEX_BASE64, $raw_svg_content)) {
132 if (preg_match(self::REGEX_SCRIPT, $raw_svg_content)) {
136 if (preg_match(self::REGEX_FOREIGN_OBJECT, $raw_svg_content)) {
145 return function (\DOMDocument $dom, \Closure $closure):
bool {
146 $attributes_looper =
function (\DOMNode $node, \Closure $closure) use (&$attributes_looper):
bool {
147 foreach ($node->attributes as $attribute) {
148 if ($closure($attribute->name)) {
149 $this->rejection_message .= sprintf(
150 $this->rejection_message_elements .
' (%s)',
156 foreach ($node->childNodes as $child) {
157 if ($child instanceof \DOMElement && !$attributes_looper($child, $closure)) {
163 foreach ($dom->getElementsByTagName(
"*") as $element) {
164 if ($attributes_looper($element, $closure) ===
false) {
Data transfer object that carries the raw SVG data as a string, created from trusted sources.
PreProcessor which checks SVGs for scripts and other malicious content.
__construct(?string $rejection_message=null, ?string $additional_message_script=null, ?string $additional_message_base64=null, ?string $additional_message_foreign_object=null, ?string $additional_message_elements=null)
string $rejection_message
string $rejection_message_foreign_object
const REGEX_FOREIGN_OBJECT
process(FileStream $stream, Metadata $metadata)
This method gets invoked by the file upload service to process the file with the help of the processo...
string $rejection_message_base64
hasContentScriptTag(string $raw_svg_content)
string $rejection_message_script
getDomDocument(string $raw_svg_content)
string $rejection_message_elements
isSVG(Metadata $metadata)
checkStream(FileStream $stream)
The base interface for all filesystem streams.