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" }