restruct / silverstripe-svg-images
为 Silverstripe(Assets/Uploads)提供基本的 SVG 图像支持
Requires
- silverstripe/cms: ~3.1
Suggests
- stevie-mayhew/silverstripe-svg: Adds additional SVG Template methods
README
此模块可以与通过 AssetAdmin 添加的任何文件以及与 'File/Image(/SVGImage)' 的 many_many 关系一起使用(无需修改)。
如果安装了 stevie-mayhew/silverstripe-svg 模块,则此模块会公开 stevie-mayhew/silverstripe-svg 模块的 SVG 模板助手和方法。请参阅“用法”。
SVG 安全
SVG 可能会暴露大量可能的攻击向量,其中大多数都是众所周知的且未修补的。基本上,你应该将 SVG 视为与 HTML/JS 相当的浏览器可执行格式,但浏览器中几乎没有内置的漏洞防护。在某些情况下,例如在服务器端解析 XML 时,SVG 也可能带来服务器端风险,如文件包含(XML 外部实体攻击)、fork bombs(十亿笑攻击)以及可能的其他数十种攻击。请参阅“安全注意事项”。
作为一般规则,仅与受信任的 SVG 一起工作(由受信任的用户创建和上传)。通过 img 标签加载的 SVG 提供了比内联 SVG 代码更高的安全性(例如,没有脚本执行)。
安装
在 config.yml 中允许 svg 作为 'File' 的扩展
SilverStripe\Assets\File:
allowed_extensions:
- svg
接下来,将 svg 添加到 assets 文件夹中 htaccess 文件中允许的扩展列表中。
新代码库
最佳选项是使用 many_many 和 UploadField::setAllowedMaxFileNumber(1),因为 File/Upload 会尝试实例化 has_one 关系指定的类名,因此会回退到 Image 而不是 SVGImage。
或者简单地告诉注入器使用 SVGImage 类而不是 Image,请参阅下面的 Yaml 配置(对于常规图像回退到 Image 类)。
或者(可能不太理想)将 has_one 关系设置为 'SVGImage' 子类。
现有代码库/站点(或模块)的选项
如果可能,您可以简单地更改关系以指向 SVGImage 类(可能需要重新添加现有关系)。
或者添加以下配置以使 has_one 的 UploadFields 指向 'Image' 加载为 .svg 文件的 SVGImage(这是另一种方法,而不是回退到 many_many,这可能会与其他模块(如也使用注入器的 FocusedImage)冲突)。
SilverStripe\Core\Injector\Injector: Image: class: SVGImage
允许 SVG 在 Scaffolded UploadFields 中使用
Scaffolded UploadFields 到 'Image' 可能需要告知允许 SVG 图像(目前已在 master 中修复)。
$field->setAllowedFileCategories('image');
还可以临时修改 /Framework/model/fieldtypes/ForeignKey 大约第 33 行以使 Scaffolded has_one UploadFields 的 Image 关系允许 SVG(临时,因为目前正在 master 中修复)。
... if($hasOneClass && singleton($hasOneClass) instanceof Image) { $field = new UploadField($relationName, $title); // CHANGE: //$field->getValidator()->setAllowedExtensions(array('jpg', 'jpeg', 'png', 'gif')); // TO: $field->setAllowedFileCategories('image'); } else ...
用法
在 SilverStripe 模板中,将其视为处理正常图像的方式(不包括格式化/缩放功能)。对于缩放/添加类等,此模块集成了 SVG 模板助手(需要 stevie-mayhew/silverstripe-svg 模块)。
<!-- add svg as image --> <img src="$Image.URL" /> <!-- or, for example when using Foundation interchange to have separate/responsive versions: --> <img src="$Image_Mobile.URL" data-interchange="[$Image_Desktop.URL, medium]" />
<!-- add inline svg (the raw SVG file will be inserted, see the .SVG helper for more subtle inlining) --> {$Image.SVG_RAW_Inline} <!-- Test for SVG and fallback to regular image methods, for example when the image may be multiple formats (eg SVG/PNG/JPG) --> <% if $Image.IsSVG %> {$Image.SVG_RAW_Inline} <% else %> $Image.SetWidth(1200) <% end_if %>
通过 '.SVG' 方法公开了额外的辅助函数,用于宽度、高度、大小、填充以及添加额外类。 (需要额外的模块:stevie-mayhew/silverstripe-svg)
<!-- add inline svg (slightly sanitized) --> {$Image.SVG} <!-- add a part of an SVG by ID inline --> {$Image.SVG.LimitID('ParticularID')}
<!-- change width --> {$Image.SVG.width(200)} <!-- change height --> {$Image.SVG.height(200)} <!-- change size (width and height) --> {$Image.SVG.size(100,100)} <!-- change fill --> {$Image.SVG.fill('#FF9933')} <!-- add class --> {$Image.SVG.extraClass('awesome-svg')}
这些选项也可以链式调用。
{$SVG('name').fill('#45FABD').width(200).height(100).extraClass('awesome-svg')}
安全注意事项
目前我不知道任何完全清理不受信任 SVG 的方法。正则表达式不适合这项工作,并且任何 PHP XML 解析器都至少容易受到一些攻击向量(如文件包含)的影响。以下是一个 已知攻击向量的详细列表。
DOMPurify 是一个基于浏览器/JS的库,似乎做得相当不错(但它使用的是JS/NodeJS,而不是PHP)。基于PHP的库,虽然提供了一些保护,但使用(可能危险的)XML解析的有 svg-sanitizer 及 SVG Sanitizer。
SVG裁剪及额外的操作(将要添加到本模块中)
http://www.silverstrip.es/blog/svg-in-the-silverstripe-backend/
裁剪基本上可以通过使用 viewBox,结合svg的宽度/高度属性(所有都是可选的)来实现 PHP SVG类(Imagemagick):https://github.com/oscarotero/imagecow 简单渲染SVG到JPG/PNG:http://stackoverflow.com/questions/10289686/rendering-an-svg-file-to-a-png-or-jpeg-in-php
PHP Cairo (PECL,并不是一个好的选择):https://php.ac.cn/manual/en/class.cairosvgsurface.php
PHP SVG Iconizr (CLI CSS/SVG/PNG精灵生成器):https://github.com/jkphl/iconizr