micshk / 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 模块(由 composer 推荐),则此模块公开了该模块的 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 添加到资产文件夹中 htaccess 文件中允许的扩展名列表中。
新代码库
最佳选项是使用 UploadField::setAllowedMaxFileNumber(1) 的 many_manys,因为 File/Upload 会尝试为 has_ones 实例化指定的类名,因此会回退到 Image 而不是 SVGImage。
或者,简单地告诉注入器使用 SVGImage 类而不是 Image,请参阅下面的 Yaml 配置(对于常规图像回退到 Image 类)。
或者(可能不受欢迎),将 has_one 关系设置为 'SVGImage' 子类。
现有代码库/网站的选项
如果可能,您可以简单地更改关系以指向 SVGImage 类(现有关系可能需要重新添加?)
或者,添加以下配置以使 has_one 的 UploadFields 指向 'Image' 在 .svg 文件中加载为 SVGImage(这是另一种方法,而不是回退到 many_manys,这可能会与其他模块(如也使用注入器的 FocusedImage)发生冲突)。
SilverStripe\Core\Injector\Injector: Image: class: SVGImage
允许 SVG 在 Scaffolded UploadFields 中使用
可能需要告诉 Scaffolded UploadFields 以允许 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](https://github.com/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 解析器都至少容易受到某些攻击向量(如文件包含)的影响。以下是已知攻击向量的详细列表:[defusedxml](https://pypi.ac.cn/project/defusedxml/#php)
DOMPurify 是一个基于浏览器/JavaScript的库,看起来做得很不错(但它是JavaScript/NodeJS,而不是PHP)。基于PHP的库,提供一些保护功能,但使用(可能危险的)XML解析的包括 svg-sanitizer 和 SVG Sanitizer。
SVG裁剪及额外操作(待添加到本模块中)
http://www.silverstrip.es/blog/svg-in-the-silverstripe-backend/
裁剪基本上可以使用 viewBox 实现,结合svg的width/height属性(全部为可选)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(命令行CSS/SVG/PNG精灵生成器):https://github.com/jkphl/iconizr