我正在使用d3.js创建图表作为SVG。这些图表是根据经过身份验证的用户的选择动态生成的。生成这些图表后,用户可以选择将生成的SVG下载为PNG或PDF。
目前的工作流程如下:
// JAVASC
// get the element containing generated SVG
var svg = document.getElementById("chart-container");
// Extract the data as SVG text string
var svg_xml = (new XMLSerializer).serializeToString(svg);
// Submit the <FORM> to the server.
var form = document.getElementById("svgform");
form['output_format'].value = output_format; // can be either "pdf" or "png"
form['data'].value = svg_xml ;
form.submit();
FORM元素是一个隐藏的表单,用于POST数据:
<form id="svgform" method="post" action="conversion.php">
<input type="hidden" id="output_format" name="output_format" value="">
<input type="hidden" id="data" name="data" value="">
</form>
PHP文件将提供的SVG数据保存为临时文件:
// check for valid session, etc - omitted for brevity
$xmldat = $_POST['data']; // serialized XML representing the SVG element
if(simplexml_load_string($xmldat)===FALSE) { die; } // reject invalid XML
$fileformat = $_POST['output_format']; // chosen format for output; PNG or PDF
if ($fileformat != "pdf" && $fileformat != "png" ){ die; } // limited options for format
$fileformat = escapeshellarg($fileformat); // escape shell arguments that might have snuck in
// generate temporary file names with tempnam() - omitted for brevity
$handle = fopen($infile, "w");
fwrite($handle, $xmldat);
fclose($handle);
运行转换实用程序,该实用程序读取临时文件($ infile)并在指定的$ fileformat(PDF或PNG)中创建新文件($ outfile)。然后,生成的新文件将返回到浏览器,并删除临时文件:
// headers etc generated - omitted for brevity
readfile($outfile);
unlink($infile); // delete temporary infile
unlink($outfile); // delete temporary outfile
我已调查converting the SVG to a PNG using JavaScript (canvg(), then toDataURL, then document.write),可能会将其用于生成PNG,但不允许转换为PDF。
所以: 在将convert.php写入文件之前,如何最好地清理或过滤提供给convert.php的SVG数据? SVG清理的当前状态是什么? PHP中有什么可用的?我应该使用whitelist-based approach来清理提供给conversion.php的SVG数据,还是有更好的方法?
(我不知道XSLT,虽然我可以尝试学习它;我希望尽可能地在PHP中保持清理。使用Windows Server 2008,所以任何使用外部工具的解决方案都需要在生态系统。)
答案 0 :(得分:3)
我正在使用xml和PHP,但我不确定你的问题。请把它作为一个想法/建议,而不是更多。
SimpleXML使用libxml加载xml内容。 http://www.php.net/manual/en/simplexml.requirements.php
您可以使用以下方法禁用外部实体:
libxml_disable_entity_loader (TRUE)
http://www.php.net/manual/en/function.libxml-disable-entity-loader.php
在使用simpleXML加载文件之前。
然后您可以验证SVG架构
http://us3.php.net/manual/en/domdocument.schemavalidate.php 要么 http://us3.php.net/manual/en/domdocument.validate.php
我唯一担心的是svg可能包含脚本元素。 http://www.w3.org/TR/SVG/script.html#ScriptElement
这里有关于1.1 DTD的信息: http://www.w3.org/Graphics/SVG/1.1/DTD/svg-framework.mod http://www.w3.org/TR/2003/REC-SVG11-20030114/REC-SVG11-20030114.pdf
您可以为SVG DTD提供脚本元素的修改版本或循环元素以防止脚本元素出现。
它不会是完美的,但至少比没有好。
答案 1 :(得分:1)
您需要使用XML解析器+白名单对SVG进行清理。
由于SVG已经有多种执行代码的方式,以后的扩展可能会添加其他方法,因此您根本无法将“已知危险”的构造列入黑名单。只要正确处理所有XML极端情况(例如XSLT样式表,实体扩展,外部实体引用),就可以将安全元素和属性列入白名单。
示例实现:https://github.com/alnorris/SVG-Sanitizer/blob/master/SvgSanitizer.php(MIT许可证)或https://github.com/darylldoyle/svg-sanitizer(GPL v2许可证)
有关在选择要支持的功能时必须考虑的攻击媒介的更多信息:
答案 2 :(得分:1)
您可以使用SVG Sanitize软件包:https://packagist.org/packages/enshrined/svg-sanitize
在撰写此答案之日已安装了500k。
use enshrined\svgSanitize\Sanitizer;
// Create a new sanitizer instance
$sanitizer = new Sanitizer();
// Load the dirty svg
$dirtySVG = file_get_contents('filthy.svg');
// Pass it to the sanitizer and get it back clean
$cleanSVG = $sanitizer->sanitize($dirtySVG);
// Now do what you want with your clean SVG/XML data