risu 1.4.9 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.ci +18 -0
- data/LICENSE +3 -3
- data/NEWS.markdown +45 -0
- data/README.markdown +10 -2
- data/Rakefile +15 -5
- data/TODO.markdown +45 -19
- data/lib/risu.rb +2 -1
- data/lib/risu/base/schema.rb +3 -4
- data/lib/risu/base/template_base.rb +11 -11
- data/lib/risu/cli/application.rb +23 -15
- data/lib/risu/exceptions.rb +1 -3
- data/lib/risu/models/host.rb +1 -1
- data/lib/risu/models/item.rb +90 -18
- data/lib/risu/models/plugin.rb +2 -2
- data/lib/risu/models/reference.rb +93 -0
- data/lib/risu/parsers/nessus/nessus_sax_listener.rb +28 -30
- data/lib/risu/renderers.rb +6 -0
- data/lib/risu/renderers/nilrenderer.rb +25 -0
- data/lib/risu/templates/assets.rb +5 -2
- data/lib/risu/templates/cover_sheet.rb +1 -1
- data/lib/risu/templates/exec_summary.rb +19 -4
- data/lib/risu/templates/executive_summary.rb +20 -5
- data/lib/risu/templates/finding_statistics.rb +1 -1
- data/lib/risu/templates/findings_host.rb +27 -8
- data/lib/risu/templates/findings_summary.rb +14 -1
- data/lib/risu/templates/findings_summary_with_pluginid.rb +1 -1
- data/lib/risu/templates/graphs.rb +5 -1
- data/lib/risu/templates/host_summary.rb +8 -4
- data/lib/risu/templates/ms_patch_summary.rb +1 -1
- data/lib/risu/templates/ms_update_summary.rb +1 -1
- data/lib/risu/templates/notable.rb +1 -2
- data/lib/risu/templates/notable_detailed.rb +8 -8
- data/lib/risu/templates/pci_compliance.rb +1 -1
- data/lib/risu/templates/stig_findings_summary.rb +135 -0
- data/lib/risu/templates/technical_findings.rb +5 -17
- data/lib/risu/templates/template.rb +1 -1
- data/risu.gemspec +1 -2
- metadata +43 -28
@@ -1,6 +1,6 @@
|
|
1
1
|
module Risu
|
2
|
-
module
|
3
|
-
class
|
2
|
+
module Templates
|
3
|
+
class Assets < Risu::Base::TemplateBase
|
4
4
|
|
5
5
|
#
|
6
6
|
#
|
@@ -14,9 +14,12 @@ module Risu
|
|
14
14
|
}
|
15
15
|
end
|
16
16
|
|
17
|
+
#undef :render if method_defined? :render
|
17
18
|
#
|
18
19
|
#
|
19
20
|
def render(output)
|
21
|
+
output.font_size 10
|
22
|
+
|
20
23
|
output.text Report.classification.upcase, :align => :center
|
21
24
|
output.text "\n"
|
22
25
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Risu
|
2
|
-
module
|
2
|
+
module Templates
|
3
3
|
class ExecSummary < Risu::Base::TemplateBase
|
4
4
|
|
5
5
|
#
|
@@ -40,13 +40,27 @@ module Risu
|
|
40
40
|
|
41
41
|
output.text "A total of #{Host.count} hosts were found and scanned for vulnerabities.\n\n"
|
42
42
|
|
43
|
-
output.text "There were #{Item.risks.count} vulnerabilities found during this scan. Of these, #{Item.high_risks.count} were high vulnerabilities, #{Item.medium_risks.count} were medium vulnerabilities, #{Item.low_risks.count} were low vulnerabilities and #{Item.info_risks.count} were information findings.\n\n"
|
43
|
+
output.text "There were #{Item.risks.count} vulnerabilities found during this scan. Of these, #{Item.critical_risks.count} were critical vulnerabilities,#{Item.high_risks.count} were high vulnerabilities, #{Item.medium_risks.count} were medium vulnerabilities, #{Item.low_risks.count} were low vulnerabilities and #{Item.info_risks.count} were information findings.\n\n"
|
44
44
|
|
45
45
|
output.text "Scan Statistics", :style => :bold
|
46
46
|
output.text "\n"
|
47
47
|
|
48
|
-
output.table([[
|
49
|
-
|
48
|
+
output.table([[
|
49
|
+
"Number of hosts",
|
50
|
+
"Number of risks",
|
51
|
+
"Critical Risks",
|
52
|
+
"High Risks",
|
53
|
+
"Medium Risks",
|
54
|
+
"Low Risks",
|
55
|
+
"Info Risks"],
|
56
|
+
[
|
57
|
+
Host.count,
|
58
|
+
Item.risks.count,
|
59
|
+
Item.critical_risks.count,
|
60
|
+
Item.high_risks.count,
|
61
|
+
Item.medium_risks.count,
|
62
|
+
Item.low_risks.count,
|
63
|
+
Item.info_risks.count]],
|
50
64
|
:cell_style => { :padding =>12 }, :width => output.bounds.width)
|
51
65
|
output.text "\n\n\n"
|
52
66
|
|
@@ -72,6 +86,7 @@ module Risu
|
|
72
86
|
cury = output.y
|
73
87
|
#move_down 550
|
74
88
|
output.image Host.windows_os_graph, :width => 250, :at => [output.bounds.left, cury]
|
89
|
+
output.image Item.stigs_severity_graph, :width => 250, :at => [output.bounds.right - 250, cury]
|
75
90
|
end
|
76
91
|
end
|
77
92
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Risu
|
2
|
-
module
|
2
|
+
module Templates
|
3
3
|
class ExecutiveSummaryDetailed < Risu::Base::TemplateBase
|
4
4
|
|
5
5
|
#
|
@@ -9,7 +9,7 @@ module Risu
|
|
9
9
|
{
|
10
10
|
:name => "exec_summary_detailed",
|
11
11
|
:author => "Ed Davison <EDavison@getmns.com>",
|
12
|
-
:version => "0.0.
|
12
|
+
:version => "0.0.3",
|
13
13
|
:description => "Generates a detailed executive summary report"
|
14
14
|
}
|
15
15
|
end
|
@@ -61,8 +61,22 @@ module Risu
|
|
61
61
|
output.text "Scan Statistics", :style => :bold
|
62
62
|
output.text "\n"
|
63
63
|
|
64
|
-
headers = [
|
65
|
-
|
64
|
+
headers = [
|
65
|
+
"Number of hosts",
|
66
|
+
"Number of risks",
|
67
|
+
"Critical Risks",
|
68
|
+
"High Risks",
|
69
|
+
"Medium Risks",
|
70
|
+
"Low Risks",
|
71
|
+
"Info Risks"]
|
72
|
+
data = [[
|
73
|
+
Host.count,
|
74
|
+
Item.risks.count,
|
75
|
+
Item.critical_risks.count,
|
76
|
+
Item.high_risks.count,
|
77
|
+
Item.medium_risks.count,
|
78
|
+
Item.low_risks.count,
|
79
|
+
Item.info_risks.count]]
|
66
80
|
|
67
81
|
output.table([headers] + data, :header => true, :row_colors => ['ffffff', 'f0f0f0']) do
|
68
82
|
row(0).style(:font_style => :bold, :background_color => 'cccccc')
|
@@ -77,12 +91,13 @@ module Risu
|
|
77
91
|
output.text "There were #{Item.risks.count} risks found during this scan. Of these, #{Item.high_risks.count} were High risk vulnerabilities. High risk vulnerabilities require immediate attention to handle as they are relatively easy for attackers to exploit frequently resulting in full access to affected systems. There were #{Item.medium_risks.count} findings which were Medium risk. High risk vulnerabilities are harder to exploit and may not result in full control of the affected system and should be addressed rapidly and with priority. There were #{Item.low_risks.count} findings which were Low risk vulnerabilities. These risks usually let attackers gain information about your network making it easier for launching more advanced attacks and should be handled in a timely manner. And #{Item.info_risks.count} findings which were information findings.\n"
|
78
92
|
output.text "\n"
|
79
93
|
|
94
|
+
crit_host_count = Item.where(:severity => 4).group(:host_id).all.count
|
80
95
|
high_host_count = Item.where(:severity => 3).group(:host_id).all.count
|
81
96
|
medium_host_count = Item.where(:severity => 2).group(:host_id).all.count
|
82
97
|
low_host_count = Item.where(:severity => 1).group(:host_id).all.count
|
83
98
|
info_host_count = Item.where(:severity => 0).group(:host_id).all.count
|
84
99
|
|
85
|
-
output.text "There were #{high_host_count} hosts with High risk vulnerabilities, #{medium_host_count} hosts with Medium risk vulnerabilities, #{low_host_count} hosts with Low risk vulnerabilities and #{info_host_count} hosts with information findings."
|
100
|
+
output.text "There were #{crit_host_count} hosts with Critical risk vulnerabilities, #{high_host_count} hosts with High risk vulnerabilities, #{medium_host_count} hosts with Medium risk vulnerabilities, #{low_host_count} hosts with Low risk vulnerabilities and #{info_host_count} hosts with information findings."
|
86
101
|
output.text "\n"
|
87
102
|
|
88
103
|
output.text "The following output.table shows the top 5 vulnerabilities that were found. These are the most important vulnerabilities to address as they represent a sizeable footprint for an attacker to exploit in an attempt to compromise.\n"
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Risu
|
2
|
-
module
|
2
|
+
module Templates
|
3
3
|
class FindingsHost < Risu::Base::TemplateBase
|
4
4
|
|
5
5
|
#
|
@@ -9,7 +9,7 @@ module Risu
|
|
9
9
|
{
|
10
10
|
:name => "findings_host",
|
11
11
|
:author => "hammackj",
|
12
|
-
:version => "0.0.
|
12
|
+
:version => "0.0.2",
|
13
13
|
:description => "Generates a findings report by host"
|
14
14
|
}
|
15
15
|
end
|
@@ -17,12 +17,14 @@ module Risu
|
|
17
17
|
#
|
18
18
|
#
|
19
19
|
def render(output)
|
20
|
+
output.font_size 10
|
21
|
+
|
20
22
|
output.text Report.classification.upcase, :align => :center
|
21
23
|
output.text "\n"
|
22
24
|
|
23
25
|
output.font_size(22) { output.text Report.title, :align => :center }
|
24
26
|
output.font_size(18) {
|
25
|
-
output.text "Findings Summary Report", :align => :center
|
27
|
+
output.text "Findings Summary by Host Report", :align => :center
|
26
28
|
output.text "\n"
|
27
29
|
output.text "This report was prepared by\n#{Report.author}", :align => :center
|
28
30
|
}
|
@@ -31,13 +33,30 @@ module Risu
|
|
31
33
|
|
32
34
|
Host.sorted.each do |host|
|
33
35
|
if host.items.high_risks_unique_sorted.all.size > 0 or host.items.medium_risks_unique_sorted.all.size > 0
|
34
|
-
output.font_size(
|
35
|
-
|
36
|
-
}
|
36
|
+
output.font_size(16) do
|
37
|
+
|
38
|
+
host_string = "#{host.ip}"
|
39
|
+
host_string << " (#{host.fqdn})" if host.fqdn != nil
|
40
|
+
|
41
|
+
output.text "#{host_string}", :style => :bold
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
if host.items.critical_risks_unique_sorted.all.size > 0
|
46
|
+
output.font_size(12) do
|
47
|
+
output.fill_color "551A8B"
|
48
|
+
output.text "Critical Findings", :style => :bold
|
49
|
+
output.fill_color "000000"
|
50
|
+
end
|
51
|
+
|
52
|
+
host.items.high_risks_unique_sorted.each do |item|
|
53
|
+
name = Plugin.find_by_id(item.plugin_id).plugin_name
|
54
|
+
output.text "#{name}"
|
55
|
+
end
|
37
56
|
end
|
38
57
|
|
39
58
|
if host.items.high_risks_unique_sorted.all.size > 0
|
40
|
-
output.font_size(
|
59
|
+
output.font_size(12) {
|
41
60
|
output.fill_color "FF0000"
|
42
61
|
output.text "High Findings", :style => :bold
|
43
62
|
output.fill_color "000000"
|
@@ -50,7 +69,7 @@ module Risu
|
|
50
69
|
end
|
51
70
|
|
52
71
|
if host.items.medium_risks_unique_sorted.all.size > 0
|
53
|
-
output.font_size(
|
72
|
+
output.font_size(12) {
|
54
73
|
output.fill_color "FF8040"
|
55
74
|
output.text "Medium Findings", :style => :bold
|
56
75
|
output.fill_color "000000"
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Risu
|
2
|
-
module
|
2
|
+
module Templates
|
3
3
|
class FindingsSummary < Risu::Base::TemplateBase
|
4
4
|
|
5
5
|
#
|
@@ -32,6 +32,19 @@ module Risu
|
|
32
32
|
|
33
33
|
output.text "\n\n\n"
|
34
34
|
|
35
|
+
output.font_size(20) do
|
36
|
+
output.fill_color "551A8B"
|
37
|
+
output.text "Critical Findings", :style => :bold
|
38
|
+
output.fill_color "000000"
|
39
|
+
end
|
40
|
+
|
41
|
+
Item.critical_risks_unique_sorted.each do |item|
|
42
|
+
name = Plugin.find_by_id(item.plugin_id).plugin_name
|
43
|
+
count = Item.where(:plugin_id => item.plugin_id).count
|
44
|
+
|
45
|
+
output.text "#{count} - #{name}"
|
46
|
+
end
|
47
|
+
|
35
48
|
output.font_size(20) do
|
36
49
|
output.fill_color "FF0000"
|
37
50
|
output.text "High Findings", :style => :bold
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Risu
|
2
|
-
module
|
2
|
+
module Templates
|
3
3
|
class Graphs < Risu::Base::TemplateBase
|
4
4
|
|
5
5
|
#
|
@@ -54,6 +54,10 @@ module Risu
|
|
54
54
|
output.start_new_page
|
55
55
|
|
56
56
|
output.image Host.windows_os_graph, :width => 500, :height => 375, :position => :center
|
57
|
+
|
58
|
+
output.start_new_page
|
59
|
+
|
60
|
+
output.image Item.stigs_severity_graph, :width => 500, :height => 375, :position => :center
|
57
61
|
end
|
58
62
|
end
|
59
63
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Risu
|
2
|
-
module
|
2
|
+
module Templates
|
3
3
|
class HostSummary < Risu::Base::TemplateBase
|
4
4
|
|
5
5
|
#
|
@@ -9,7 +9,7 @@ module Risu
|
|
9
9
|
{
|
10
10
|
:name => "host_summary",
|
11
11
|
:author => "hammackj",
|
12
|
-
:version => "0.0.
|
12
|
+
:version => "0.0.2",
|
13
13
|
:description => "Generates a Host Summary Report"
|
14
14
|
}
|
15
15
|
end
|
@@ -31,13 +31,14 @@ module Risu
|
|
31
31
|
|
32
32
|
results = Array.new
|
33
33
|
|
34
|
-
headers = ["Hostname", "Total", "High", "Medium", "Low", "Info"]
|
35
|
-
header_widths = {0 =>
|
34
|
+
headers = ["Hostname", "Total", "Critical", "High", "Medium", "Low", "Info"]
|
35
|
+
header_widths = {0 => 140, 1 => 62, 2 => 62, 3 => 62, 4 => 62, 5 => 62, 6 => 62}
|
36
36
|
|
37
37
|
Host.sorted.each do |host|
|
38
38
|
row = Array.new
|
39
39
|
|
40
40
|
total = Item.risks.where(:host_id => host.id).count
|
41
|
+
crit = Item.critical_risks.where(:host_id => host.id).count
|
41
42
|
high = Item.high_risks.where(:host_id => host.id).count
|
42
43
|
medium = Item.medium_risks.where(:host_id => host.id).count
|
43
44
|
low = Item.low_risks.where(:host_id => host.id).count
|
@@ -45,6 +46,7 @@ module Risu
|
|
45
46
|
|
46
47
|
row.push(host.name)
|
47
48
|
row.push(total)
|
49
|
+
row.push(crit)
|
48
50
|
row.push(high)
|
49
51
|
row.push(medium)
|
50
52
|
row.push(low)
|
@@ -57,6 +59,8 @@ module Risu
|
|
57
59
|
row(0).style(:font_style => :bold, :background_color => 'D0D0D0')
|
58
60
|
cells.borders = [:top, :bottom, :left, :right]
|
59
61
|
end
|
62
|
+
|
63
|
+
output.number_pages "<page> of <total>", :at => [output.bounds.right - 75, 0], :width => 150, :page_filter => :all
|
60
64
|
end
|
61
65
|
end
|
62
66
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Risu
|
2
|
-
module
|
3
|
-
class
|
2
|
+
module Templates
|
3
|
+
class NotableDetailed < Risu::Base::TemplateBase
|
4
4
|
|
5
5
|
#
|
6
6
|
#
|
@@ -9,7 +9,7 @@ module Risu
|
|
9
9
|
{
|
10
10
|
:name => "notable_detailed",
|
11
11
|
:author => "hammackj",
|
12
|
-
:version => "0.0.
|
12
|
+
:version => "0.0.4",
|
13
13
|
:description => "Notable Vulnerabilities Detailed"
|
14
14
|
}
|
15
15
|
end
|
@@ -20,15 +20,15 @@ module Risu
|
|
20
20
|
output.text Report.classification.upcase, :align => :center
|
21
21
|
output.text "\n"
|
22
22
|
|
23
|
-
output.font_size(22)
|
23
|
+
output.font_size(22) do
|
24
24
|
output.text Report.title, :align => :center
|
25
|
-
|
25
|
+
end
|
26
26
|
|
27
|
-
output.font_size(18)
|
27
|
+
output.font_size(18) do
|
28
28
|
output.text "Notable Vulnerabilities", :align => :center
|
29
29
|
output.text "\n"
|
30
30
|
output.text "This report was prepared by\n#{Report.author}", :align => :center
|
31
|
-
|
31
|
+
end
|
32
32
|
|
33
33
|
output.text "\n\n\n"
|
34
34
|
|
@@ -41,7 +41,7 @@ module Risu
|
|
41
41
|
data = Item.top_10_sorted_raw
|
42
42
|
|
43
43
|
unique_risks = Array.new
|
44
|
-
unique_risks << Hash[:title => "
|
44
|
+
unique_risks << Hash[:title => "Notable Findings", :color => "9B30FF", :values => Item.top_10_sorted_raw[0..9]]
|
45
45
|
counter = 1
|
46
46
|
|
47
47
|
unique_risks.each do |h|
|
@@ -0,0 +1,135 @@
|
|
1
|
+
module Risu
|
2
|
+
module Templates
|
3
|
+
class StigFindingsSummary < Risu::Base::TemplateBase
|
4
|
+
|
5
|
+
# Initializes the template loading metadata
|
6
|
+
#
|
7
|
+
def initialize ()
|
8
|
+
@template_info =
|
9
|
+
{
|
10
|
+
:name => "stig_findings_summary",
|
11
|
+
:author => "hammackj",
|
12
|
+
:version => "0.0.1",
|
13
|
+
:description => "DISA Stig findings summary report"
|
14
|
+
}
|
15
|
+
|
16
|
+
@output = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
#
|
20
|
+
#
|
21
|
+
def header
|
22
|
+
@output.text Report.classification.upcase, :align => :center
|
23
|
+
@output.text "\n"
|
24
|
+
|
25
|
+
@output.font_size(22) do
|
26
|
+
@output.text Report.title, :align => :center
|
27
|
+
end
|
28
|
+
|
29
|
+
@output.font_size(18) do
|
30
|
+
@output.text "Stig Findings Summary", :align => :center
|
31
|
+
@output.text "\n"
|
32
|
+
@output.text "This report was prepared by\n#{Report.author}", :align => :center
|
33
|
+
end
|
34
|
+
|
35
|
+
@output.text "\n\n\n"
|
36
|
+
end
|
37
|
+
|
38
|
+
# Creates a list of hosts from an list of Items
|
39
|
+
#
|
40
|
+
# @param items
|
41
|
+
def host_list_from_plugin_id(plugin_id)
|
42
|
+
Host.where('id IN (:hosts)', :hosts => Item.where(:plugin_id => plugin_id).select(:host_id).select('host_id AS id'))
|
43
|
+
end
|
44
|
+
|
45
|
+
def host_list_text(hosts)
|
46
|
+
host_string = ""
|
47
|
+
hosts.all.each do |host|
|
48
|
+
host_string << "#{host.ip}"
|
49
|
+
host_string << " (#{host.netbios})" if host.netbios
|
50
|
+
host_string << ", "
|
51
|
+
end
|
52
|
+
|
53
|
+
return host_string.chomp!(", ")
|
54
|
+
end
|
55
|
+
|
56
|
+
# Generates stig finding text for
|
57
|
+
#
|
58
|
+
# @param categeory I/II/III for each stig severity
|
59
|
+
def stig_findings_text(categeory="I")
|
60
|
+
if categeory != "I" || categeory != "II" || categeory != "III"
|
61
|
+
return
|
62
|
+
end
|
63
|
+
|
64
|
+
stigs = Item.stig_findings(categeory).group(:plugin_id)
|
65
|
+
|
66
|
+
stigs.each do |stig|
|
67
|
+
@output.text "#{stig.plugin_name}", :size => 16
|
68
|
+
hosts = host_list_from_plugin_id(stig.plugin_id)
|
69
|
+
hosts_string = host_list_text(hosts)
|
70
|
+
|
71
|
+
if hosts.count > 1
|
72
|
+
@output.text "<b>Hosts</b>: #{hosts_string}", :inline_format => true
|
73
|
+
else
|
74
|
+
@output.text "<b>Host</b>: #{hosts_string}", :inline_format => true
|
75
|
+
end
|
76
|
+
|
77
|
+
@output.text "<b>Risk</b>: #{stig.plugin.risk_factor}", :inline_format => true
|
78
|
+
@output.text "<b>CVE Reference</b>: #{ref_string(stig.plugin.references.cve)}", :inline_format => true
|
79
|
+
@output.text "<b>IAVA Reference</b>: #{ref_string(stig.plugin.references.iava)}", :inline_format => true
|
80
|
+
|
81
|
+
if stig.plugin.description != nil
|
82
|
+
@output.text "\nDescription:", :style => :bold
|
83
|
+
@output.text stig.plugin.description
|
84
|
+
end
|
85
|
+
|
86
|
+
@output.text "\n"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
#
|
91
|
+
#
|
92
|
+
def ref_string ref
|
93
|
+
return "" if ref == nil
|
94
|
+
|
95
|
+
ref_string = ""
|
96
|
+
ref.each do |r|
|
97
|
+
ref_string << r.value + ", "
|
98
|
+
end
|
99
|
+
|
100
|
+
ref_string.chomp!(", ")
|
101
|
+
end
|
102
|
+
|
103
|
+
# Called during the rendering process
|
104
|
+
#
|
105
|
+
def render(output)
|
106
|
+
@output = output
|
107
|
+
|
108
|
+
@output.font_size 10
|
109
|
+
|
110
|
+
header
|
111
|
+
|
112
|
+
if Item.stig_findings("I").count > 0
|
113
|
+
@output.text "<color rgb='551A8B'>Category I Findings</color>", :size => 18, :style => :bold, :inline_format => true
|
114
|
+
stig_findings_text("I")
|
115
|
+
end
|
116
|
+
|
117
|
+
if Item.stig_findings("II").count > 0
|
118
|
+
@output.start_new_page
|
119
|
+
@output.text "<color rgb='FF0000'>Category II Findings</color>", :size => 18, :style => :bold, :inline_format => true
|
120
|
+
stig_findings_text("II")
|
121
|
+
end
|
122
|
+
|
123
|
+
if Item.stig_findings("III").count > 0
|
124
|
+
@output.start_new_page
|
125
|
+
@output.text "<color rgb='FF8040'>Category III Findings</color>", :size => 18, :style => :bold, :inline_format => true
|
126
|
+
stig_findings_text("III")
|
127
|
+
end
|
128
|
+
|
129
|
+
@output.number_pages "<page> of <total>", :at => [@output.bounds.right - 75, 0], :width => 150, :page_filter => :all
|
130
|
+
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|