diff --git a/helpers/helper.rb b/helpers/helper.rb
index 6eaa2e7e..ecd0b03f 100644
--- a/helpers/helper.rb
+++ b/helpers/helper.rb
@@ -254,7 +254,7 @@ def url_escape_hash(hash)
end
v = new_v
- elsif (k == 'remediation') || (k == 'overview') || (k == 'poc') || (k == 'affected_hosts') || (k == 'references')
+ elsif k.start_with?('remediation', 'overview', 'poc', 'affected_hosts', 'references')
new_v = "#{v}"
v = new_v
end
diff --git a/model/master.rb b/model/master.rb
index ba725f29..7129757b 100644
--- a/model/master.rb
+++ b/model/master.rb
@@ -95,8 +95,22 @@ class TemplateFindings
property :nist_rating, String, :required => false
property :language, String, required: false
+ has n, :translations, 'TemplateFindingsTranslation'
end
+class TemplateFindingsTranslation
+ include DataMapper::Resource
+
+ property :id, Serial
+ property :language, String, required: true, length: 100
+ property :title, String, length: 200
+ property :overview, String, length: 20_000, required: false
+ property :poc, String, length: 20_000, required: false
+ property :remediation, String, length: 20_000, required: false
+ property :references, String, length: 20_000, required: false
+
+ belongs_to :finding, 'TemplateFindings', required: true
+ end
class Findings
include DataMapper::Resource
@@ -353,7 +367,7 @@ class Reports
property :user_defined_variables, String, length: 10_000
property :scoring, String, length: 100
- property :language, String, required: false
+ property :language, String, required: true, default: "undefined" ,length: 50
end
class Attachments
diff --git a/routes/master.rb b/routes/master.rb
index be55485e..7b0dd8eb 100644
--- a/routes/master.rb
+++ b/routes/master.rb
@@ -39,6 +39,9 @@
post '/master/findings/new' do
data = url_escape_hash(request.POST)
+ @available_languages = config_options['languages']
+ return "Language \"#{data["language"]}\" is absent from the config file" if !@available_languages.include?(data["language"])
+
if config_options['dread']
data['dread_total'] = data['damage'].to_i + data['reproducability'].to_i + data['exploitability'].to_i + data['affected_users'].to_i + data['discoverability'].to_i
end
@@ -63,6 +66,9 @@
data['risk'] = severity_val + likelihood_val
end
+ # split out language
+ language = data['language']
+ data.delete('language')
# Create NIST800 finding in the main database
if(config_options["nist800"])
# call nist800 helper function
@@ -85,6 +91,8 @@
# find the id of the newly created finding so we can link mappings to it
@newfinding = TemplateFindings.first(title: data['title'], order: [:id.desc], limit: 1)
+ # save translation
+ @finding.translations.create(:finding => @finding, :language => language, :title => data['title'], :poc => data['poc'], :overview => data['overview'], :remediation => data['remediation'])
# save mapping data
if config_options['nessusmap'] && nessusdata['pluginid']
nessusdata['templatefindings_id'] = @finding.id
@@ -111,7 +119,6 @@
get '/master/findings/:id/edit' do
@master = true
- @languages = config_options['languages']
@dread = config_options['dread']
@cvss = config_options['cvss']
@cvssv3 = config_options['cvssv3']
@@ -121,6 +128,7 @@
@burpmap = config_options['burpmap']
@vulnmap = config_options['vulnmap']
+ @available_languages = config_options['languages']
# Check for kosher name in report name
id = params[:id]
@@ -154,7 +162,9 @@
data['approved'] = data['approved'] == 'on'
# to prevent title's from degenerating with >, etc. [issue 237]
- data['title'] = data['title'].gsub('&', '&')
+ if data.has_key? 'title'
+ data['title'] = data['title'].gsub('&', '&')
+ end
if config_options['dread']
data['dread_total'] = data['damage'].to_i + data['reproducability'].to_i + data['exploitability'].to_i + data['affected_users'].to_i + data['discoverability'].to_i
@@ -208,8 +218,33 @@
data.delete('msf_ref')
vulnmappingdata['templatefindings_id'] = id
+ # split out and save any translation data
+ translated_parts_from_findings = @finding.translations.all(:finding_id => id)
+ translated_parts_from_findings.each do |translated_parts_from_finding|
+ translated_finding_data = {}
+ if data["title_#{translated_parts_from_finding.language}"].empty?
+ status 500
+ return "Title can't be empty"
+ end
+ # to prevent title's from degenerating with >, etc. [issue 237]
+ translated_finding_data['title'] = data["title_#{translated_parts_from_finding.language}"].to_s.gsub('&', '&')
+ data.delete("title_#{translated_parts_from_finding.language}")
+ translated_finding_data["overview"] = data["overview_#{translated_parts_from_finding.language}"]
+ data.delete("overview_#{translated_parts_from_finding.language}")
+ translated_finding_data["poc"] = data["poc_#{translated_parts_from_finding.language}"]
+ data.delete("poc_#{translated_parts_from_finding.language}")
+ translated_finding_data["remediation"] = data["remediation_#{translated_parts_from_finding.language}"]
+ data.delete("remediation_#{translated_parts_from_finding.language}")
+ translated_finding_data["references"] = data["references_#{translated_parts_from_finding.language}"]
+ data.delete("references_#{translated_parts_from_finding.language}")
+ if !translated_parts_from_finding.update(translated_finding_data)
+ return "
The following error(s) were found while trying to update translated finding data:
#{translated_parts_from_finding.errors.full_messages.flatten.join(', ')}
"
+ end
+ end
# Update the finding with templated finding stuff
- @finding.update(data)
+ if !@finding.update(data)
+ return "
The following error(s) were found while trying to update finding:
#{@finding.errors.full_messages.flatten.join(', ')}
"
+ end
# save nessus mapping data to db
if config_options['nessusmap']
@@ -232,6 +267,53 @@
redirect to('/master/findings')
end
+post '/master/findings/:id/add_language' do
+ id = params[:id]
+
+ #check if finding exist
+ finding = TemplateFindings.first(:id => id)
+ return "No Such Finding #{id}" if finding.nil?
+
+ error = mm_verify(request.POST)
+ return error if error.size > 1
+ data = url_escape_hash(request.POST)
+
+ @available_languages = config_options['languages']
+ return "Language \"#{data["language"]}\" is absent from the config file" if !@available_languages.include?(data["language"])
+
+
+ finding_translation = finding.translations.first(:language => data["language"])
+ return 'The translation already exists' if !finding_translation.nil?
+
+ #if the finding language is undefined, we update the language "undefined"
+ if finding.translations.empty?
+ translation = finding.translations.create(:finding => finding, :language => data["language"], :title => finding.title, :overview => finding.overview, :poc => finding.poc, :remediation => finding.remediation, :references => finding.references)
+ else
+ translation = finding.translations.create(:finding => finding, :language => data["language"])
+ end
+ return "Error while creating translation : #{translation.errors.full_messages.flatten.join(', ')}" if !translation.saved?
+ redirect to("/master/findings/#{id}/edit")
+end
+
+get '/master/findings/:id/define_language/:language' do
+ id = params[:id]
+ language = params[:language]
+
+ finding = TemplateFindings.first(:id => id)
+ return "No Such Finding #{id}" if finding.nil?
+
+ @available_languages = config_options['languages']
+ return "Language \"#{data["language"]}\" is absent from the config file" if !@available_languages.include?(language)
+
+ finding_translation = finding.translations.first(:language => language)
+ return 'The translation already exists' if !finding_translation.nil?
+
+ finding_translation = finding.translations.first(:language => "undefined")
+ finding_translation.update(:language => language)
+ return "Error while updating translations : #{translation.errors.full_messages.flatten.join(', ')}" if !translation.saved?
+
+ redirect to("/master/findings/#{id}/edit")
+end
# Delete a template finding
get '/master/findings/delete/:id' do
id = params[:id]
@@ -240,6 +322,11 @@
finding = TemplateFindings.first(id: current_id)
return "No Such Finding : #{current_id}" if finding.nil?
+ # delete the entries
+ finding.translations.each do |translation|
+ translation.destroy
+ end
+
# delete the entries
finding.destroy
diff --git a/routes/report.rb b/routes/report.rb
index 428b4e37..64eb5e66 100644
--- a/routes/report.rb
+++ b/routes/report.rb
@@ -26,9 +26,13 @@
# Create a report
get '/report/new' do
@templates = Xslt.all
- @assessment_types = config_options['report_assessment_types']
- @languages = config_options['languages']
- haml :new_report, encode_html: true
+ if config_options['languages']
+ @languages = config_options['languages']
+ else
+ return "No language found in your config.json file. Please, add your langagues in the config.json file."
+ end
+ @assessment_types = config_options["report_assessment_types"]
+ haml :new_report, :encode_html => true
end
# Create a report
@@ -373,7 +377,11 @@
@templates = Xslt.all(order: [:report_type.asc])
@plugin_side_menu = get_plugin_list('user')
@assessment_types = config_options['report_assessment_types']
- @languages = config_options['languages']
+ if config_options['languages']
+ @languages = config_options['languages']
+ else
+ return "No language found in your config.json file. Please, add your langagues in the config.json file."
+ end
@risk_scores = %w[Risk DREAD CVSS CVSSv3 RiskMatrix NIST800]
return 'No Such Report' if @report.nil?
@@ -754,7 +762,7 @@
@languages = config_options['languages']
# Query for all Findings
- @findings = TemplateFindings.all(approved: true, order: [:title.asc])
+ @findings = TemplateFindings.all(approved: true, order: [:title.asc], :translations => {:language => [@report.language]}) + TemplateFindings.all(order: [:title.asc], :translations => nil )
haml :findings_add, encode_html: true
end
@@ -776,12 +784,22 @@
params[:finding].each do |finding|
templated_finding = TemplateFindings.first(id: finding.to_i)
- templated_finding.id = nil
- attr = templated_finding.attributes
- attr.delete(:approved)
+ # Set translation in approriate attributes
+ if !templated_finding.translations.first(:language => @report.language).nil?
+ templated_finding.title = templated_finding.translations.first(:language => @report.language).title
+ templated_finding.overview = templated_finding.translations.first(:language => @report.language).overview
+ templated_finding.poc = templated_finding.translations.first(:language => @report.language).poc
+ templated_finding.remediation = templated_finding.translations.first(:language => @report.language).remediation
+ templated_finding.references = templated_finding.translations.first(:language => @report.language).references
+ end
+
+ templated_finding.id = nil
+ attr = templated_finding.attributes
+ attr.delete(:approved)
+ attr.delete(:translations)
attr['master_id'] = finding.to_i
- @newfinding = Findings.new(attr)
- @newfinding.report_id = id
+ @newfinding = Findings.new(attr)
+ @newfinding.report_id = id
# because of multiple scores we need to make sure all are set
# => leave it up to the user to make the calculation if they switch mid report
diff --git a/serpico.rb b/serpico.rb
index 25a976ed..c7743205 100644
--- a/serpico.rb
+++ b/serpico.rb
@@ -53,4 +53,13 @@
end
+# Replace old language field for a translation class
+if !Pathname("verify/language_db").exist?
+ @findings = TemplateFindings.all(:language.not => nil)
+ @findings.each do |finding|
+ finding.translations.create(:finding => finding, :language => finding.language, :title => finding.title, :overview =>finding.overview, :poc => finding.poc, :remediation => finding.remediation, :references => finding.references)
+ end
+ File.open("verify/language_db", "w") {}
+ puts "|+| [#{DateTime.now.strftime('%d/%m/%Y %H:%M')}] Updated database"
+end
Rack::Handler::WEBrick.run Server, server_options
diff --git a/verify/blank b/verify/blank
new file mode 100644
index 00000000..e69de29b
diff --git a/views/findings_add.haml b/views/findings_add.haml
index f6b7c91d..f44f9d8d 100644
--- a/views/findings_add.haml
+++ b/views/findings_add.haml
@@ -34,9 +34,8 @@
%table{ :style => "width: 100%" }
- @findings.each do |finding|
- if finding.type == type
- - if @languages and @languages.size > 1
- - next unless (finding.language == @report.language) or (@report.language == "English" and finding.language == nil)
%tr
+ - if finding.translations.first.nil?
%td.searchable{ :style => "width: 80%", :"data-index" => "#{finding.title.downcase}" }
- if @autoadd
- if @autoadd_findings.include?(finding.id.to_s) and not @dup_findings.include?(finding.id)
@@ -68,9 +67,42 @@
%a.btn.btn-info{ :href => "/master/findings/#{finding.id}/preview" }
%i.icon-play-circle.icon-white{ :title => "Preview" }
- else
+ %a{ :class => "btn btn-info", :href => "/master/findings/#{finding.id}/preview"}
+ %i{:class => 'icon-play-circle icon-white', :title => 'Preview'}
+ - elsif !finding.translations.first(:language => @report.language).nil?
+ %td.searchable{ :style => "width: 80%", :"data-index" => "#{finding.translations.first(:language => @report.language).title.downcase}" }
+ - if @autoadd
+ - if @autoadd_findings.include?(finding.id.to_s) and not @dup_findings.include?(finding.id)
+ %input{ :id => "finding_#{finding.id}", :type => "checkbox", :name => "finding[]", :value => "#{finding.id}", :checked => "" }
+ - else
+ %input{ :id => "finding_#{finding.id}", :type => "checkbox", :name => "finding[]", :value => "#{finding.id}" }
+ - else
+ %input{ :id => "finding_#{finding.id}", :type => "checkbox", :name => "finding[]", :value => "#{finding.id}" }
+ %label.control-label{ :for => "finding_#{finding.id}" }
+ #{finding.translations.first(:language => @report.language).title}
+ - if @dup_findings
+ - if @dup_findings.include?(finding.id)
+ .label.label-warning Duplicate
+ - if finding.translations.first(:language => @report.language).overview
+ %i.icon-chevron-down#actionButton{ "data-toggle" => "collapse", "data-target" => "#info_#{finding.id}" }
+ .info.collapse.out{ :id => "info_#{finding.id}" }
+ #{finding.translations.first(:language => @report.language).overview.gsub("","
").gsub("","").gsub("","•").gsub("","")}
+ - if @autoadd_hosts
+ - @autoadd_hosts.keys.each do |x|
+ - if finding.id == x.to_i
+ - @autoadd_hosts[x].each do |ip|
+ .label.label-default #{ip}
+ - iplist = @autoadd_hosts[x].join(",")
+ %input{ :type => "hidden", :name => "finding#{finding.id.to_s}", :value => "#{iplist}" }
+ %td.searchable{ :style => "width: 20%", :"data-index" => "#{finding.title.downcase}" }
+ - if @master
+ %a.btn.btn-warning{ :href => "/master/findings/#{finding.id}/edit" }
+ %i.icon-pencil.icon-white{ :title => "Edit" }
%a.btn.btn-info{ :href => "/master/findings/#{finding.id}/preview" }
%i.icon-play-circle.icon-white{ :title => "Preview" }
-
+ - else
+ %a{ :class => "btn btn-info", :href => "/master/findings/#{finding.id}/preview"}
+ %i{:class => 'icon-play-circle icon-white', :title => 'Preview'}
%br
%input.btn.btn-default{ :type => "submit", :value => "Add" }
%a.btn.btn-default{ :href => "/report/#{@report.id}/findings" }
diff --git a/views/findings_edit.haml b/views/findings_edit.haml
index e0574fcf..48fce281 100644
--- a/views/findings_edit.haml
+++ b/views/findings_edit.haml
@@ -3,14 +3,73 @@
.col-md-10
%br
- %h2 #{@finding.title}
+ - if @report
+ %h2 #{@finding.title}
+ - if @master
+ %h2
+ - if @finding.translations.empty?
+ #{@finding.title}
+ - else
+ #{@finding.translations.first.title}
+ %label{ :class => "control-label", :for => "language_panel" }
+ %a{:href=> '#language_panel', "data-toggle"=>'modal', :class=>'btn btn-info'}
+ Language panel
+ .modal{:id=>'language_panel', :class=>'modal hide fade', :tabindex=>'-1', :role=>'dialog', "aria-labelledby"=>'modal-label', "aria-hidden"=>'true'}
+ .modal-body
+ %h3 Language panel
+ %form{ :action => "/master/findings/#{@finding.id}/add_language", :method => "post", :class => "form-horizontal"}
+ //checking whether all language in config are supported by finding
+ - all_language_supported = true
+ - @available_languages.each do |language|
+ - if @finding.translations.first(:language => language).nil?
+ - all_language_supported = false
+ - if not all_language_supported
+ - if @finding.translations.empty?
+ In wich language is this finding :
+ - else
+ Add language to this finding:
+ %select{:name => "language"}
+ - @available_languages.each do |language|
+ - if @finding.translations.first(:language => language).nil?
+ %option #{language}
+ - if @finding.translations.empty?
+ %input.btn.btn-default{ :type => "submit", :value => 'Define Language'}
+ -else
+ %input.btn.btn-default{ :type => "submit", :value => 'Add Language'}
+ - else
+ You can't add any new language to this finding template, as it already support every configured language.
+ - if @finding.translations.count > 1
+ %div
+ %h4 Select wich language to show
+ - @finding.translations.each do |translation|
+ %input{ :type => "checkbox", :class => "language_checkbox", :name => translation.language, :style => "margin-top: 0px;"} #{" " + translation.language}
+ %br
+ -else
+ %div{:style => "display: none"}
+ %h4 Select wich language to show
+ - @finding.translations.each do |translation|
+ %input{ :type => "checkbox", :class => "language_checkbox", :name => translation.language, :style => "margin-top: 0px;"} #{" " + translation.language}
+ %br
+ %br
%br
%form.form-horizontal{ :method => "post", :enctype => "application/x-www-form-urlencoded" }
- .control-group
- %label.control-label{ :for => "title" } Title
- .controls
- %input{ :type => "text", :name => "title", :value => "#{@finding.title}" }
+ - if @report
+ .control-group
+ %label.control-label{ :for => "title" } Title
+ .controls
+ %input{ :type => "text", :name => "title", :value => "#{@finding.title}" }
+ - if @master
+ - @finding.translations.each do |translation|
+ .control-group{:class => "language_#{translation.language}", :style => "display: none;"}
+ %label{ :class => "control-label", :for => "title" } Title (#{translation.language})
+ .controls
+ %input{ :type => 'text', :name => "title_#{translation.language}", :value => "#{translation.title}"}
+ - if @finding.translations.empty?
+ .control-group
+ %label{ :class => "control-label", :for => "title" } Title
+ .controls
+ %input{ :type => 'text', :name => "title", :value => "#{@finding.title}"}
-if !@master
.control-group
%label.control-label{ :for => "assessment_type" } Assessment Type
@@ -30,17 +89,6 @@
%input{ :type=>"checkbox", :name => "approved", :checked=>"checked" }
- else
%input{ :type=>"checkbox", :name => "approved" }
- - if @master
- - if @languages and @languages.size > 1
- .control-group
- %label.control-label{ :for => "language" } Language Setting
- .controls
- %select#language{ :name => "language" }
- - @languages.each do |type|
- - if @finding.language == type
- %option{ :selected => "selected" } #{type}
- - else
- %option #{type}
- if @vulnmap
.control-group
%label.control-label{ :for => "existingvulnmaps" } Vuln IDs mapped to this finding
@@ -682,95 +730,267 @@
%option{ :selected => "selected" } #{type}
- else
%option #{type}
- .control-group
- %label.control-label{ :for => "overview" }
- %a.btn.btn-info{ :href=> "#modaloverview", "data-toggle" => "modal" }
- Overview
- .modal.modal.hide.fade#modaloverview{ :tabindex => "-1", :role => "dialog", "aria-labelledby" => "modal-label", "aria-hidden" => "true"}
- .modal-header
- %button.close{ :type => "button", "data-dismiss" => "modal", "aria-hidden" => "true" }
- x
- %h3#modal-label
- Meta Markup
- .modal-body
- %p
- There are markup sets you can use in any field. This text is converted inside of Microsoft Word.
- %p.text-error
- YOU MUST CLOSE ALL TAGS. OTHERWISE YOU CAN DESTROY ALL TEXT FORMATTING. SEE EXAMPLES BELOW.
- %b
- Review the finding "TEST - Markup Tester" for a clear example. As always, press preview to see the finding in Word.
- %h2
- {{ URL }}
- %p
- If you place {{ URL }} in any field the text will be hyperlinked, otherwise hyperlinking is ignored.
- %br
- %h2
- <<CUSTOMER>>
- %p
- If you place <<CUSTOMER>> in a finding the customer name will be substituted in the finding. This is particularly helpful in the Templated Findings.
- %br
- %br
- %code
- Overall <<CUSTOMER>> was found to have a strong...
- %br
- %br
- Will generate the following inside of a report:
- %br
- %br
- %code
- Overall AcmeCorporation was found to have a strong...
- %h2
- Bullets
- %p
- Shortcut : CTRL + ALT + w
- %br
- Place the bulleted text inbetween a *- and a -* like so:
- %br
- %br
- %code
- *- Bulleted text goes here -*
- %h2
- Paragraph Heading Text
- %p
- Shortcut : CTRL + ALT + q
- %br
- Place the heading inbetween a [== and a ==] like so:
- %br
- %br
- %code
- [== Heading text goes here ==]
- %h2
- Italics
- %p
- Shortcut : CTRL + ALT + x
- %br
- Italicize the paragraph containing [~~ and a ~~]:
- %br
- %br
- %code
- [~~ Italics ~~]
- %h2
- Code
- %p
- Shortcut : CTRL + ALT + c
- %br
- Place code inbetween a [[[ and a ]]] like below. CODE CANNOT STRETCH MULTIPLE LINES.
- %br
- %br
- %code
- [[[ code, code goes here ]]]
- .controls
- %textarea.input-xxlarge.allowMarkupShortcut#overview{ :rows => "10", :name => "overview" }
- - if @finding
- - if @finding.overview
- #{meta_markup(@finding.overview)}
- .control-group
- %label.control-label{ :for => "pocu" } Proof of Concept
- .controls
- %textarea.input-xxlarge.allowMarkupShortcut#pocu{ :rows => "10", :name => "poc" }
- - if @finding
- - if @finding.poc
- #{meta_markup(@finding.poc)}
+ - if @report
+ .control-group
+ %label.control-label{ :for => "overview" }
+ %a.btn.btn-info{ :href=> "#modaloverview", "data-toggle" => "modal" }
+ Overview
+ .modal.modal.hide.fade#modaloverview{ :tabindex => "-1", :role => "dialog", "aria-labelledby" => "modal-label", "aria-hidden" => "true"}
+ .modal-header
+ %button.close{ :type => "button", "data-dismiss" => "modal", "aria-hidden" => "true" }
+ x
+ %h3#modal-label
+ Meta Markup
+ .modal-body
+ %p
+ There are markup sets you can use in any field. This text is converted inside of Microsoft Word.
+ %p.text-error
+ YOU MUST CLOSE ALL TAGS. OTHERWISE YOU CAN DESTROY ALL TEXT FORMATTING. SEE EXAMPLES BELOW.
+ %b
+ Review the finding "TEST - Markup Tester" for a clear example. As always, press preview to see the finding in Word.
+ %h2
+ {{ URL }}
+ %p
+ If you place {{ URL }} in any field the text will be hyperlinked, otherwise hyperlinking is ignored.
+ %br
+ %h2
+ <<CUSTOMER>>
+ %p
+ If you place <<CUSTOMER>> in a finding the customer name will be substituted in the finding. This is particularly helpful in the Templated Findings.
+ %br
+ %br
+ %code
+ Overall <<CUSTOMER>> was found to have a strong...
+ %br
+ %br
+ Will generate the following inside of a report:
+ %br
+ %br
+ %code
+ Overall AcmeCorporation was found to have a strong...
+ %h2
+ Bullets
+ %p
+ Shortcut : CTRL + ALT + w
+ %br
+ Place the bulleted text inbetween a *- and a -* like so:
+ %br
+ %br
+ %code
+ *- Bulleted text goes here -*
+ %h2
+ Paragraph Heading Text
+ %p
+ Shortcut : CTRL + ALT + q
+ %br
+ Place the heading inbetween a [== and a ==] like so:
+ %br
+ %br
+ %code
+ [== Heading text goes here ==]
+ %h2
+ Italics
+ %p
+ Shortcut : CTRL + ALT + x
+ %br
+ Italicize the paragraph containing [~~ and a ~~]:
+ %br
+ %br
+ %code
+ [~~ Italics ~~]
+ %h2
+ Code
+ %p
+ Shortcut : CTRL + ALT + c
+ %br
+ Place code inbetween a [[[ and a ]]] like below. CODE CANNOT STRETCH MULTIPLE LINES.
+ %br
+ %br
+ %code
+ [[[ code, code goes here ]]]
+ .controls
+ %textarea.input-xxlarge.allowMarkupShortcut#overview{ :rows => '10', :name => "overview"}
+ - if @finding
+ - if @finding.overview
+ #{meta_markup(@finding.overview)}
+ - if @master
+ - @finding.translations.each do |translation|
+ .control-group{:class => "language_#{translation.language}", :style => "display: none;"}
+ %label{ :class => "control-label", :for => "overview" }
+ %a{:href=> '#modaloverview', "data-toggle"=>'modal', :class=>'btn btn-info'}
+ Overview (#{translation.language})
+ .modal{:id=>'modaloverview', :class=>'modal hide fade', :tabindex=>'-1', :role=>'dialog', "aria-labelledby"=>'modal-label', "aria-hidden"=>'true'}
+ .modal-header
+ %button{:type=>'button', :class=>'close', "data-dismiss"=>"modal", "aria-hidden"=>"true"}
+ x
+ %h3{:id=>"modal-label"}
+ Meta Markup
+ .modal-body
+ %p
+ There are four markup sets you can use in the Overview and the Remediation summary. This text is converted inside of Microsoft Word.
+ %p{:class=>"text-error"}
+ YOU MUST CLOSE ALL TAGS. OTHERWISE YOU CAN DESTROY ALL TEXT FORMATTING. SEE EXAMPLES BELOW.
+ %b
+ Review the finding "TEST - Markup Tester" for a clear example. As always, press preview to see the finding in Word.
+ %h2
+ <<CUSTOMER>>
+ %p
+ If you place <<CUSTOMER>> in a finding the customer name will be substituted in the finding. This is particularly helpful in the Templated Findings.
+ %br
+ %br
+ %code
+ Overall <<CUSTOMER>> was found to have a strong...
+ %br
+ %br
+ Will generate the following inside of a report:
+ %br
+ %br
+ %code
+ Overall AcmeCorporation was found to have a strong...
+ %h2
+ Bullets
+ %p
+ Shortcut : CTRL + ALT + w
+ %br
+ Place the bulleted text inbetween a *- and a -* like so:
+ %br
+ %br
+ %code
+ *- Bulleted text goes here -*
+ %h2
+ Paragraph Heading Text
+ %p
+ Shortcut : CTRL + ALT + q
+ %br
+ Place the heading inbetween a [== and a ==] like so:
+ %br
+ %br
+ %code
+ [== Heading text goes here ==]
+ %h2
+ Italics
+ %p
+ Shortcut : CTRL + ALT + x
+ %br
+ Italicize the paragraph containing [~~ and a ~~]:
+ %br
+ %br
+ %code
+ [~~ Italics ~~]
+ %h2
+ Code
+ %p
+ Shortcut : CTRL + ALT + c
+ %br
+ Place code inbetween a [[[ and a ]]] like below. CODE CANNOT STRETCH MULTIPLE LINES.
+ %br
+ %br
+ %code
+ [[[ code, code goes here ]]]
+ .controls
+ %textarea{ :rows => '10', :class => 'input-xxlarge allowMarkupShortcut', :id => 'overview', :name => "overview_#{translation.language}"}
+ - if @finding
+ - if @finding.overview
+ #{meta_markup(translation.overview)}
+ - if @finding.translations.empty?
+ .control-group
+ %label{ :class => "control-label", :for => "overview" }
+ %a{:href=> '#modaloverview', "data-toggle"=>'modal', :class=>'btn btn-info'}
+ Overview
+ .modal{:id=>'modaloverview', :class=>'modal hide fade', :tabindex=>'-1', :role=>'dialog', "aria-labelledby"=>'modal-label', "aria-hidden"=>'true'}
+ .modal-header
+ %button{:type=>'button', :class=>'close', "data-dismiss"=>"modal", "aria-hidden"=>"true"}
+ x
+ %h3{:id=>"modal-label"}
+ Meta Markup
+ .modal-body
+ %p
+ There are four markup sets you can use in the Overview and the Remediation summary. This text is converted inside of Microsoft Word.
+ %p{:class=>"text-error"}
+ YOU MUST CLOSE ALL TAGS. OTHERWISE YOU CAN DESTROY ALL TEXT FORMATTING. SEE EXAMPLES BELOW.
+ %b
+ Review the finding "TEST - Markup Tester" for a clear example. As always, press preview to see the finding in Word.
+ %h2
+ <<CUSTOMER>>
+ %p
+ If you place <<CUSTOMER>> in a finding the customer name will be substituted in the finding. This is particularly helpful in the Templated Findings.
+ %br
+ %br
+ %code
+ Overall <<CUSTOMER>> was found to have a strong...
+ %br
+ %br
+ Will generate the following inside of a report:
+ %br
+ %br
+ %code
+ Overall AcmeCorporation was found to have a strong...
+ %h2
+ Bullets
+ %p
+ Shortcut : CTRL + ALT + w
+ %br
+ Place the bulleted text inbetween a *- and a -* like so:
+ %br
+ %br
+ %code
+ *- Bulleted text goes here -*
+ %h2
+ Paragraph Heading Text
+ %p
+ Shortcut : CTRL + ALT + q
+ %br
+ Place the heading inbetween a [== and a ==] like so:
+ %br
+ %br
+ %code
+ [== Heading text goes here ==]
+ %h2
+ Italics
+ %p
+ Shortcut : CTRL + ALT + x
+ %br
+ Italicize the paragraph containing [~~ and a ~~]:
+ %br
+ %br
+ %code
+ [~~ Italics ~~]
+ %h2
+ Code
+ %p
+ Shortcut : CTRL + ALT + c
+ %br
+ Place code inbetween a [[[ and a ]]] like below. CODE CANNOT STRETCH MULTIPLE LINES.
+ %br
+ %br
+ %code
+ [[[ code, code goes here ]]]
+ .controls
+ %textarea{ :rows => '10', :class => 'input-xxlarge allowMarkupShortcut', :id => 'overview', :name => "overview"}
+ - if @finding
+ - if @finding.overview
+ #{meta_markup(@finding.overview)}
+ - if @report
+ .control-group
+ %label.control-label{ :for => "pocu" } Proof of Concept
+ .controls
+ %textarea.input-xxlarge.allowMarkupShortcut#pocu{ :rows => "10", :name => "poc" }
+ - if @finding
+ - if @finding.poc
+ #{meta_markup(@finding.poc)}
+ - if @master
+ - @finding.translations.each do |translation|
+ .control-group{:class => "language_#{translation.language}", :style => "display: none;"}
+ %label{ :class => "control-label", :for => "pocu" } Proof of Concept (#{translation.language})
+ .controls
+ %textarea{ :rows => '10', :class => 'input-xxlarge allowMarkupShortcut', :name => "poc_#{translation.language}", :id => "pocu"}
+ #{meta_markup(translation.poc)}
+ - if @finding.translations.empty?
+ .control-group
+ %label{ :class => "control-label", :for => "pocu" } Proof of Concept
+ .controls
+ %textarea{ :rows => '10', :class => 'input-xxlarge allowMarkupShortcut', :name => "poc", :id => "pocu"}
+ #{meta_markup(@finding.poc)}
- attachments=''
- if @attaches
- @attaches.each do |attach|
@@ -802,20 +1022,50 @@
- if @finding
- if @finding.affected_hosts
#{meta_markup(@finding.affected_hosts)}
- .control-group
- %label.control-label{ :for => "remediation" } Remediation
- .controls
- %textarea.input-xxlarge.allowMarkupShortcut{ :rows => "10", :name => "remediation" }
- - if @finding
- - if @finding.remediation
+ - if @report
+ .control-group
+ %label.control-label{ :for => "remediation" } Remediation
+ .controls
+ %textarea.input-xxlarge.allowMarkupShortcut{ :rows => "10", :name => "remediation" }
+ - if @finding
+ - if @finding.remediation
+ #{meta_markup(@finding.remediation)}
+ - if @master
+ - @finding.translations.each do |translation|
+ .control-group{:class => "language_#{translation.language}", :style => "display: none;"}
+ %label{ :class => "control-label", :for => "remediation" } Remediation (#{translation.language})
+ .controls
+ %textarea{ :rows => '10', :class => 'input-xxlarge allowMarkupShortcut', :name => "remediation_#{translation.language}"}
+ #{meta_markup(translation.remediation)}
+ - if @finding.translations.empty?
+ .control-group
+ %label{ :class => "control-label", :for => "remediation" } Remediation
+ .controls
+ %textarea{ :rows => '10', :class => 'input-xxlarge allowMarkupShortcut', :name => "remediation"}
#{meta_markup(@finding.remediation)}
- .control-group
- %label.control-label{ :for => "references" } References (One Per Line)
- .controls
- %textarea.input-xxlarge.allowMarkupShortcut{ :rows => "5", :name => "references" }
- - if @finding
- - if @finding.references
- #{meta_markup(@finding.references)}
+ - if @report
+ .control-group
+ %label{ :class => "control-label", :for => "references" } References (One Per Line)
+ .controls
+ %textarea{ :rows => '5', :class => 'input-xxlarge allowMarkupShortcut', :name => 'references'}
+ - if @finding
+ - if @finding.references
+ #{meta_markup(@finding.references)}
+ - if @master
+ - @finding.translations.each do |translation|
+ .control-group{:class => "language_#{translation.language}", :style => "display: none;"}
+ %label{ :class => "control-label", :for => "references" } References (One Per Line) (#{translation.language})
+ .controls
+ %textarea{ :rows => '10', :class => 'input-xxlarge allowMarkupShortcut', :name => "references_#{translation.language}", :id => "references"}
+ #{meta_markup(translation.references)}
+ - if @finding.translations.empty?
+ .control-group
+ %label.control-label{ :for => "references" } References (One Per Line)
+ .controls
+ %textarea.input-xxlarge.allowMarkupShortcut{ :rows => "5", :name => "references" }
+ - if @finding
+ - if @finding.references
+ #{meta_markup(@finding.references)}
- if !@master
.control-group
%label.control-label{ :for => "notes" } Notes Data
@@ -961,3 +1211,22 @@
updateCVSSSummary(true, false);
});
});
+
+ var checkbox = document.querySelectorAll(".language_checkbox")
+ for(var i = 0 ; i < checkbox.length ; i++){
+ // script allowing display of according to selected languages
+ checkbox[i].addEventListener("change", function(e){
+ elements = document.querySelectorAll(".language_" + e.target.name)
+ var style = ""
+ if(e.target.checked === true){
+ style = "display: block;"
+ }
+ else{
+ style = "display: none;"
+ }
+ for(var j = 0 ; j < elements.length ; j++){
+ elements[j].style = style;
+ }
+ })
+ }
+ checkbox[0].click()
diff --git a/views/findings_list.haml b/views/findings_list.haml
index 939fd415..3f809330 100644
--- a/views/findings_list.haml
+++ b/views/findings_list.haml
@@ -58,7 +58,10 @@
%td.searchable{ :"data-index" => "#{finding.title.downcase}", :style => "width: 1%" }
%input.checkbox{ :type=>"checkbox", :name=>"#{finding.id}" }
%td.searchable{ :style => "width: 70%", :"data-index" => "#{finding.title.downcase}" }
- #{finding.title}
+ - if !finding.translations.first.nil?
+ #{finding.translations.first.title}
+ - else
+ #{finding.title}
- if @dread
%td.searchable{ :style => "width: 10%", :"data-index" => "#{finding.title.downcase}" }
#{finding.dread_total}
diff --git a/views/report_edit.haml b/views/report_edit.haml
index 0fb983c1..0022e100 100644
--- a/views/report_edit.haml
+++ b/views/report_edit.haml
@@ -34,6 +34,10 @@
%option{ :selected => "selected" } #{language}
- else
%option #{language}
+ - if @report.language == "undefined"
+ %option{ :selected => "selected", :value => "undefined" } #{" "}
+ - else
+ %option{ :value => "undefined" } #{" "}
%tr
%td{ :style => "width: 30%" }
%label.col-md-3{ :for => "report_name" }