Implemented pie charts
This commit is contained in:
parent
d7036b5d86
commit
bd45a3c4c8
@ -1,6 +1,13 @@
|
||||
RELEASE NOTES
|
||||
=============
|
||||
|
||||
January 12th, 2017
|
||||
------------------
|
||||
|
||||
###Pie charts
|
||||
|
||||
You can now generate pie charts for any countable data that might be in the report. You can do so using the element `<generate_piechart pieAttr="x" pieElem="y" pieHeight="z">`, where `x` is the attribute value of any element `y` in the document (useful charts would be `threatLevel` for `x` and `finding` for `y` to show a pie chart of the share of findings by threat level, or `type` for `x` and `finding` for `y` to show a pie chart of the share of findings by type). The height (and width) of the pie is set in the pieHeight attribute, where `z` is the height of the pie chart in px.
|
||||
|
||||
August 25th, 2016
|
||||
-----------------
|
||||
|
||||
|
||||
@ -121,6 +121,19 @@ who is also the co-founder/CEO of Radically Open Security.</bio>
|
||||
<generate_recommendations/>
|
||||
<!-- generated from Findings section -->
|
||||
</section>
|
||||
<section id="dataSummary">
|
||||
<title>Charts</title>
|
||||
<section id="threatlevelpie">
|
||||
<title>Findings by Threat Level</title>
|
||||
<generate_piechart pieAttr="threatLevel" pieElem="finding" pieHeight="200"/>
|
||||
</section>
|
||||
<section id="typepie">
|
||||
<title>Findings by Type</title>
|
||||
<generate_piechart pieAttr="type" pieElem="finding" pieHeight="200"/>
|
||||
</section>
|
||||
|
||||
<!-- generated from Findings section -->
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="snippets/report/methodology.xml"/>
|
||||
@ -232,7 +245,21 @@ Raw packets sent: 1681 (73.962KB) | Rcvd: 1681 (77.322KB)</pre>
|
||||
</recommendation>
|
||||
</finding>
|
||||
|
||||
|
||||
<finding id="f3" threatLevel="Low" type="XSS">
|
||||
<title>A not quite so terrible XSS issue</title>
|
||||
<description>
|
||||
<p>A description of the problem.</p>
|
||||
</description>
|
||||
<technicaldescription>
|
||||
<p>Vulnerability described in detail.</p>
|
||||
</technicaldescription>
|
||||
<impact>
|
||||
<p>Impact on security.</p>
|
||||
</impact>
|
||||
<recommendation>
|
||||
<p>A ready solution.</p>
|
||||
</recommendation>
|
||||
</finding>
|
||||
</section>
|
||||
|
||||
<section id="nonFindings">
|
||||
|
||||
@ -158,6 +158,7 @@
|
||||
<xs:element ref="img"/>
|
||||
<xs:element ref="div"/>
|
||||
<xs:element ref="generate_targets"/>
|
||||
<xs:element ref="generate_piechart"/>
|
||||
<xs:element ref="generate_recommendations"/>
|
||||
<xs:element minOccurs="0" maxOccurs="unbounded" ref="generate_findings"/>
|
||||
<xs:element minOccurs="0" maxOccurs="unbounded" ref="finding"/>
|
||||
@ -173,6 +174,18 @@
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
<xs:element name="generate_piechart">
|
||||
<xs:complexType>
|
||||
<xs:attribute ref="pieAttr" use="required"/>
|
||||
<xs:attribute ref="pieElem" use="required"/>
|
||||
<xs:attribute ref="pieHeight" use="required"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
<xs:attribute name="pieAttr" type="xs:string"/>
|
||||
<xs:attribute name="pieElem" type="xs:string"/>
|
||||
<xs:attribute name="pieHeight" type="xs:integer"/>
|
||||
|
||||
<xs:attribute name="inexecsummary">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
|
||||
313
xml/target/report.fo
Normal file
313
xml/target/report.fo
Normal file
File diff suppressed because one or more lines are too long
BIN
xml/target/report.pdf
Normal file
BIN
xml/target/report.pdf
Normal file
Binary file not shown.
@ -1,7 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs"
|
||||
xmlns:fo="http://www.w3.org/1999/XSL/Format" version="2.0">
|
||||
xmlns:fo="http://www.w3.org/1999/XSL/Format" version="2.0"
|
||||
xmlns:svg="http://www.w3.org/2000/svg" xmlns:math="http://www.w3.org/2005/xpath-functions/math"
|
||||
extension-element-prefixes="math">
|
||||
|
||||
<xsl:template match="generate_targets">
|
||||
<xsl:call-template name="generate_targets_xslt"/>
|
||||
@ -266,8 +268,9 @@
|
||||
<fo:block keep-together.within-page="always" xsl:use-attribute-sets="signaturebox">
|
||||
<fo:block xsl:use-attribute-sets="title-client">
|
||||
<xsl:call-template name="getString">
|
||||
<xsl:with-param name="stringID" select="'signed_dupe'"/>
|
||||
</xsl:call-template></fo:block>
|
||||
<xsl:with-param name="stringID" select="'signed_dupe'"/>
|
||||
</xsl:call-template>
|
||||
</fo:block>
|
||||
<fo:block>
|
||||
<fo:table width="100%" table-layout="fixed" xsl:use-attribute-sets="borders">
|
||||
<fo:table-column column-width="proportional-column-width(50)"
|
||||
@ -289,11 +292,13 @@
|
||||
</fo:table-row>
|
||||
<fo:table-row>
|
||||
<fo:table-cell xsl:use-attribute-sets="td">
|
||||
<fo:block><xsl:value-of select="/*/meta/permission_parties/client/city"/></fo:block>
|
||||
<fo:block>
|
||||
<xsl:value-of select="/*/meta/permission_parties/client/city"/>
|
||||
</fo:block>
|
||||
</fo:table-cell>
|
||||
<fo:table-cell xsl:use-attribute-sets="td">
|
||||
<fo:block><xsl:value-of
|
||||
select="/*/meta/company/city"/>
|
||||
<fo:block>
|
||||
<xsl:value-of select="/*/meta/company/city"/>
|
||||
</fo:block>
|
||||
</fo:table-cell>
|
||||
</fo:table-row>
|
||||
@ -389,11 +394,300 @@
|
||||
|
||||
<xsl:template match="generate_permission_parties">
|
||||
<xsl:for-each select="/*/meta/permission_parties/client | /*/meta/permission_parties/party">
|
||||
<xsl:if test="self::party and not(following-sibling::party)"><xsl:call-template name="getString"><xsl:with-param name="stringID" select="'permission_and'"/></xsl:call-template><xsl:text> </xsl:text></xsl:if>
|
||||
<xsl:if test="self::party and not(following-sibling::party)">
|
||||
<xsl:call-template name="getString">
|
||||
<xsl:with-param name="stringID" select="'permission_and'"/>
|
||||
</xsl:call-template>
|
||||
<xsl:text> </xsl:text>
|
||||
</xsl:if>
|
||||
<xsl:value-of select="full_name"/>
|
||||
<xsl:if test="../party[2]">, </xsl:if>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<xsl:template match="generate_piechart">
|
||||
<!-- Get the numbers -->
|
||||
<!-- generate_piechart @type="type" or "threatLevel" -->
|
||||
<xsl:variable name="pieAttr" select="@pieAttr"/>
|
||||
<xsl:variable name="pieElem" select="@pieElem"/>
|
||||
<xsl:variable name="pieHeight" as="xs:integer" select="@pieHeight"/>
|
||||
<xsl:variable name="pieTotal" select="count(//*[local-name() = $pieElem])"/>
|
||||
<!-- Create generic nodeset with values -->
|
||||
<xsl:variable name="unsortedPieTable">
|
||||
<xsl:for-each-group select="//*[local-name() = $pieElem]"
|
||||
group-by="@*[name() = $pieAttr]">
|
||||
<pieEntry>
|
||||
<pieEntryLabel>
|
||||
<xsl:value-of select="current-grouping-key()"/>
|
||||
</pieEntryLabel>
|
||||
<pieEntryCount>
|
||||
<xsl:value-of
|
||||
select="count(//*[local-name() = $pieElem][@*[name() = $pieAttr]][@* = current-grouping-key()])"
|
||||
/>
|
||||
</pieEntryCount>
|
||||
</pieEntry>
|
||||
</xsl:for-each-group>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="pieHeightHalf" as="xs:double" select="$pieHeight div 2"/>
|
||||
<!-- Now we need to sort that pieTable - custom order for threat levels, 'count' descending order for all other types -->
|
||||
<xsl:variable name="pieTable">
|
||||
<xsl:choose>
|
||||
<xsl:when test="$pieElem = 'finding' and $pieAttr = 'threatLevel'">
|
||||
<xsl:for-each select="$unsortedPieTable/pieEntry">
|
||||
<xsl:sort data-type="number" order="descending"
|
||||
select="
|
||||
(number(pieEntryLabel = 'Extreme') * 10)
|
||||
+ (number(pieEntryLabel = 'High') * 9)
|
||||
+ (number(pieEntryLabel = 'Elevated') * 8)
|
||||
+ (number(pieEntryLabel = 'Moderate') * 7)
|
||||
+ (number(pieEntryLabel = 'Low') * 6)
|
||||
+ (number(pieEntryLabel = 'Unknown') * 3)
|
||||
+ (number(pieEntryLabel = 'N/A') * 1)"/>
|
||||
<pieEntry>
|
||||
<pieEntryLabel>
|
||||
<xsl:value-of select="pieEntryLabel"/>
|
||||
</pieEntryLabel>
|
||||
<pieEntryCount>
|
||||
<xsl:value-of select="pieEntryCount"/>
|
||||
</pieEntryCount>
|
||||
</pieEntry>
|
||||
</xsl:for-each>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:for-each select="$unsortedPieTable/pieEntry">
|
||||
<xsl:sort data-type="number" order="descending" select="pieEntryCount"/>
|
||||
<pieEntry>
|
||||
<pieEntryLabel>
|
||||
<xsl:value-of select="pieEntryLabel"/>
|
||||
</pieEntryLabel>
|
||||
<pieEntryCount>
|
||||
<xsl:value-of select="pieEntryCount"/>
|
||||
</pieEntryCount>
|
||||
</pieEntry>
|
||||
</xsl:for-each>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
|
||||
</xsl:variable>
|
||||
<xsl:variable name="no_entries" select="count($pieTable/pieEntry)"/>
|
||||
<xsl:for-each select="$pieTable">
|
||||
<fo:block xsl:use-attribute-sets="p">
|
||||
<fo:table margin-top="15px">
|
||||
<!-- need some margin to make space for percentages that can't fit in the pie... -->
|
||||
<fo:table-column column-width="{$pieHeight + 50}px"/>
|
||||
<fo:table-column/>
|
||||
<fo:table-body>
|
||||
<fo:table-row keep-together.within-column="always">
|
||||
<fo:table-cell xsl:use-attribute-sets="td">
|
||||
<fo:block>
|
||||
<fo:instream-foreign-object
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<!--set the display-->
|
||||
<svg:svg>
|
||||
<!-- width and height of the viewport -->
|
||||
<xsl:attribute name="width">
|
||||
<xsl:value-of select="$pieHeight"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="height">
|
||||
<xsl:value-of select="$pieHeight"/>
|
||||
</xsl:attribute>
|
||||
<!-- viewBox to scale -->
|
||||
<xsl:attribute name="viewBox">
|
||||
<xsl:value-of
|
||||
select="concat('0 0 ', $pieHeight, ' ', $pieHeight)"
|
||||
/>
|
||||
</xsl:attribute>
|
||||
<!--call the template starting at the last slice-->
|
||||
<xsl:call-template name="pie_chart_slice">
|
||||
<xsl:with-param name="pieTotal" select="$pieTotal"/>
|
||||
<xsl:with-param name="no_entries"
|
||||
select="$no_entries"/>
|
||||
<xsl:with-param name="position" select="$no_entries"/>
|
||||
<xsl:with-param name="middle_x"
|
||||
select="$pieHeightHalf"/>
|
||||
<xsl:with-param name="middle_y"
|
||||
select="$pieHeightHalf"/>
|
||||
<xsl:with-param name="move_x" select="0"/>
|
||||
<xsl:with-param name="radius"
|
||||
select="$pieHeightHalf"/>
|
||||
</xsl:call-template>
|
||||
</svg:svg>
|
||||
</fo:instream-foreign-object>
|
||||
</fo:block>
|
||||
</fo:table-cell>
|
||||
<!-- PIE CHART LEGEND -->
|
||||
<fo:table-cell>
|
||||
<fo:block>
|
||||
<fo:table>
|
||||
<fo:table-column column-width="20px"/>
|
||||
<fo:table-column/>
|
||||
<fo:table-body>
|
||||
<xsl:for-each select="$pieTable/pieEntry">
|
||||
<fo:table-row>
|
||||
<fo:table-cell xsl:use-attribute-sets="td">
|
||||
<fo:block>
|
||||
<fo:instream-foreign-object>
|
||||
<svg:svg height="13" width="13">
|
||||
<svg:rect stroke="black" stroke-width="1"
|
||||
stroke-linejoin="round" height="11" width="11">
|
||||
<xsl:attribute name="fill">
|
||||
<xsl:call-template name="giveColor">
|
||||
<xsl:with-param name="i">
|
||||
<xsl:value-of select="position()"/>
|
||||
</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:attribute>
|
||||
</svg:rect>
|
||||
</svg:svg>
|
||||
</fo:instream-foreign-object>
|
||||
</fo:block>
|
||||
</fo:table-cell>
|
||||
<fo:table-cell xsl:use-attribute-sets="td">
|
||||
<fo:block>
|
||||
<xsl:value-of select="pieEntryLabel"/>
|
||||
</fo:block>
|
||||
</fo:table-cell>
|
||||
</fo:table-row>
|
||||
</xsl:for-each>
|
||||
</fo:table-body>
|
||||
</fo:table>
|
||||
</fo:block>
|
||||
</fo:table-cell>
|
||||
</fo:table-row>
|
||||
</fo:table-body>
|
||||
</fo:table>
|
||||
|
||||
</fo:block>
|
||||
</xsl:for-each>
|
||||
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="pie_chart_slice">
|
||||
<xsl:param name="pieTotal"/>
|
||||
<xsl:param name="position"/>
|
||||
<xsl:param name="no_entries"/>
|
||||
<xsl:param name="middle_x"/>
|
||||
<xsl:param name="middle_y"/>
|
||||
<xsl:param name="move_x"/>
|
||||
<xsl:param name="radius"/>
|
||||
<!--prepare the middle part of the arc command-->
|
||||
<xsl:variable name="middle" select="concat('M', ' ', $middle_x, ',', $middle_y)"/>
|
||||
<xsl:variable name="part" as="xs:double"
|
||||
select="sum(//pieEntry[position() <= $position]/pieEntryCount)"/>
|
||||
<!-- sum of pieEntryCounts up to this point -->
|
||||
<xsl:variable name="angle" select="($part div $pieTotal) * 360"/>
|
||||
<xsl:variable name="x" select="math:sin(3.1415292 * $angle div 180.0) * $radius"/>
|
||||
<xsl:variable name="y" select="math:cos(3.1415292 * $angle div 180.0) * $radius"/>
|
||||
<xsl:variable name="move_y" select="-$radius"/>
|
||||
<xsl:variable name="first_line" select="concat('l', ' ', $move_x, ',', $move_y)"/>
|
||||
<xsl:variable name="arc_move1" select="'0'"/>
|
||||
<xsl:variable name="arc_move2">
|
||||
<xsl:choose>
|
||||
<!--check the direction of the arc: inward or outward-->
|
||||
<xsl:when test="$angle <= 180">0</xsl:when>
|
||||
<xsl:otherwise>1</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="arc_move3" select="'1'"/>
|
||||
<xsl:variable name="arc_move" select="concat($arc_move1, ' ', $arc_move2, ',', $arc_move3)"/>
|
||||
<xsl:variable name="d"
|
||||
select="concat($middle, ' ', $first_line, ' ', 'a', $radius, ',', $radius, ' ', $arc_move, ' ', $x, ',', $radius - $y, ' ', 'z')"/>
|
||||
<!--put it all together-->
|
||||
<svg:path stroke="black" stroke-width="1" stroke-linejoin="round">
|
||||
<xsl:attribute name="fill">
|
||||
<xsl:call-template name="giveColor">
|
||||
<xsl:with-param name="i">
|
||||
<xsl:value-of select="$position"/>
|
||||
</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="d">
|
||||
<xsl:value-of select="$d"/>
|
||||
</xsl:attribute>
|
||||
</svg:path>
|
||||
<!--now the percentage-->
|
||||
<xsl:variable name="percentage" as="xs:double"
|
||||
select="(//pieEntry[position() = $position]/pieEntryCount div sum(//pieEntry/pieEntryCount)) * 100"/>
|
||||
<xsl:variable name="part_half" as="xs:double"
|
||||
select="(//pieEntry[position() = $position]/pieEntryCount div sum(//pieEntry/pieEntryCount)) div 2 * 360"/>
|
||||
<xsl:variable name="text_x"
|
||||
select="math:sin(3.1415292 * (($angle - $part_half) div 180.0)) * ($radius * 0.8)"/>
|
||||
<xsl:variable name="text_y"
|
||||
select="math:cos(3.1415292 * (($angle - $part_half) div 180.0)) * ($radius * 0.8)"/>
|
||||
<xsl:variable name="text_line_x"
|
||||
select="math:sin(3.1415292 * (($angle - $part_half) div 180.0)) * ($radius * 1.1)"/>
|
||||
<xsl:variable name="text_line_y"
|
||||
select="math:cos(3.1415292 * (($angle - $part_half) div 180.0)) * ($radius * 1.1)"/>
|
||||
<!--we either put it on the pie or have a line pointing into the slice, depending on how thick the slice is-->
|
||||
<xsl:choose>
|
||||
<xsl:when test="$percentage >= 4">
|
||||
<!--on the cream-->
|
||||
<svg:text text-anchor="middle" xsl:use-attribute-sets="DefaultFont">
|
||||
<xsl:attribute name="x">
|
||||
<xsl:value-of select="$middle_x + $text_x"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="y">
|
||||
<xsl:value-of select="$middle_y - $text_y"/>
|
||||
</xsl:attribute>
|
||||
<xsl:value-of select="format-number($percentage, '##,##0.0')"/>
|
||||
<xsl:text>%</xsl:text>
|
||||
</svg:text>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<!--extra line pointing into the slice-->
|
||||
<svg:path stroke="black" stroke-width="1" stroke-linejoin="round">
|
||||
<xsl:attribute name="fill">none</xsl:attribute>
|
||||
<xsl:attribute name="d">
|
||||
<xsl:value-of
|
||||
select="concat('M', ' ', $middle_x + $text_x, ',', $middle_y - $text_y, ' ', 'L', ' ', $middle_x + $text_line_x, ',', $middle_y - $text_line_y, ' ', 'H', ' ', $middle_x + $text_line_x - 10)"
|
||||
/>
|
||||
</xsl:attribute>
|
||||
</svg:path>
|
||||
<svg:text text-anchor="end" xsl:use-attribute-sets="DefaultFont">
|
||||
<xsl:attribute name="x">
|
||||
<xsl:value-of select="$middle_x + $text_line_x - 11"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="y">
|
||||
<xsl:value-of select="$middle_y - $text_line_y + 1"/>
|
||||
</xsl:attribute>
|
||||
<xsl:value-of select="format-number($percentage, '##,##0.0')"/>
|
||||
<xsl:text>%</xsl:text>
|
||||
</svg:text>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
<!--loop until we reach the first part-->
|
||||
<xsl:if test="$position > 1">
|
||||
<xsl:call-template name="pie_chart_slice">
|
||||
<xsl:with-param name="pieTotal" select="$pieTotal"/>
|
||||
<xsl:with-param name="position" select="$position - 1"/>
|
||||
<xsl:with-param name="no_entries" select="$no_entries"/>
|
||||
<xsl:with-param name="middle_x" select="$middle_x"/>
|
||||
<xsl:with-param name="middle_y" select="$middle_y"/>
|
||||
<xsl:with-param name="move_x" select="$move_x"/>
|
||||
<xsl:with-param name="radius" select="$radius"/>
|
||||
</xsl:call-template>
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
<xsl:template name="giveColor">
|
||||
<xsl:param name="i"/>
|
||||
<xsl:choose>
|
||||
<xsl:when test="$i = 1">#FF5C00</xsl:when>
|
||||
<xsl:when test="$i = 2">#FE9920</xsl:when>
|
||||
<xsl:when test="$i = 3">#D9D375</xsl:when>
|
||||
<xsl:when test="$i = 4">#B9A44C</xsl:when>
|
||||
<xsl:when test="$i = 5">#BEC5AD</xsl:when>
|
||||
<xsl:when test="$i = 6">#7CA982</xsl:when>
|
||||
<xsl:when test="$i = 7">#566E3D</xsl:when>
|
||||
<xsl:when test="$i = 8">#5B5F97</xsl:when>
|
||||
<xsl:when test="$i = 9">#C200FB</xsl:when>
|
||||
<xsl:when test="$i = 10">#A9E5BB</xsl:when>
|
||||
<xsl:when test="$i = 11">#98C1D9</xsl:when>
|
||||
<xsl:when test="$i = 12">#5B5F97</xsl:when>
|
||||
<xsl:when test="$i = 13">burlywood</xsl:when>
|
||||
<xsl:when test="$i = 14">cornflowerblue</xsl:when>
|
||||
<xsl:when test="$i = 15">cornsilk</xsl:when>
|
||||
<xsl:otherwise>black</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user