Land #3269 (Pro) fix report import issue

bug/bundler_fix
Trevor Rosen 2014-04-24 08:27:06 -05:00
commit e556997bf7
No known key found for this signature in database
GPG Key ID: 255ADB7A642D3928
1 changed files with 92 additions and 52 deletions

View File

@ -2172,35 +2172,63 @@ class DBManager
end
#
# Find or create a task matching this type/data
#
# TODO This method does not attempt to find. It just creates
# a report based on the passed params.
def find_or_create_report(opts)
report_report(opts)
end
# Creates a Report based on passed parameters. Does not handle
# child artifacts.
# @param opts [Hash]
# @return [Integer] ID of created report
def report_report(opts)
return if not active
::ActiveRecord::Base.connection_pool.with_connection {
wspace = opts.delete(:workspace) || workspace
path = opts.delete(:path) || (raise RuntimeError, "A report :path is required")
ret = {}
user = opts.delete(:user)
options = opts.delete(:options)
rtype = opts.delete(:rtype)
report = wspace.reports.new
report.created_by = user
report.options = options
report.rtype = rtype
report.path = path
msf_import_timestamps(opts,report)
report.save!
report = Report.new(opts)
unless report.valid?
errors = report.errors.full_messages.join('; ')
raise RuntimeError "Report to be imported is not valid: #{errors}"
end
report.state = :complete # Presume complete since it was exported
report.save
ret[:task] = report
report.id
}
end
# Creates a ReportArtifact based on passed parameters.
# @param opts [Hash] of ReportArtifact attributes
def report_artifact(opts)
artifacts_dir = Report::ARTIFACT_DIR
tmp_path = opts[:file_path]
artifact_name = File.basename tmp_path
new_path = File.join(artifacts_dir, artifact_name)
unless File.exists? tmp_path
raise DBImportError 'Report artifact file to be imported does not exist.'
end
unless (File.directory?(artifacts_dir) && File.writable?(artifacts_dir))
raise DBImportError "Could not move report artifact file to #{artifacts_dir}."
end
if File.exists? new_path
unique_basename = "#{(Time.now.to_f*1000).to_i}_#{artifact_name}"
new_path = File.join(artifacts_dir, unique_basename)
end
FileUtils.copy(tmp_path, new_path)
opts[:file_path] = new_path
artifact = ReportArtifact.new(opts)
unless artifact.valid?
errors = artifact.errors.full_messages.join('; ')
raise RuntimeError "Artifact to be imported is not valid: #{errors}"
end
artifact.save
end
#
# This methods returns a list of all reports in the database
#
@ -3793,43 +3821,55 @@ class DBManager
# Import Reports
doc.elements.each("/#{btag}/reports/report") do |report|
import_report(report, args, basedir)
end
end
# @param report [REXML::Element] to be imported
# @param args [Hash]
# @param base_dir [String]
def import_report(report, args, base_dir)
tmp = args[:ifd][:zip_tmp]
report_info = {}
report_info[:workspace] = args[:wspace]
# Should user be imported (original) or declared (the importing user)?
report_info[:user] = nils_for_nulls(report.elements["created-by"].text.to_s.strip)
report_info[:options] = nils_for_nulls(report.elements["options"].text.to_s.strip)
report_info[:rtype] = nils_for_nulls(report.elements["rtype"].text.to_s.strip)
report_info[:created_at] = nils_for_nulls(report.elements["created-at"].text.to_s.strip)
report_info[:updated_at] = nils_for_nulls(report.elements["updated-at"].text.to_s.strip)
report_info[:orig_path] = nils_for_nulls(report.elements["path"].text.to_s.strip)
report_info[:task] = args[:task]
report_info[:orig_path].gsub!(/^\./, tmp) if report_info[:orig_path]
# Only report a report if we actually have it.
# TODO: Copypasta. Seperate this out.
if ::File.exists? report_info[:orig_path]
reports_dir = ::File.join(basedir,"reports")
report_file = ::File.split(report_info[:orig_path]).last
if ::File.exists? reports_dir
unless (::File.directory?(reports_dir) && ::File.writable?(reports_dir))
raise DBImportError.new("Could not move files to #{reports_dir}")
end
else
::FileUtils.mkdir_p(reports_dir)
end
new_report = ::File.join(reports_dir,report_file)
report_info[:path] = new_report
if ::File.exists?(new_report)
::File.unlink new_report
else
report_report(report_info)
end
::FileUtils.copy(report_info[:orig_path], new_report)
yield(:msf_report, new_report) if block
end
end
report.elements.each do |e|
node_name = e.name
node_value = e.text
# These need to be converted back to arrays:
array_attrs = %w|addresses file-formats options sections|
if array_attrs.member? node_name
node_value = JSON.parse(node_value)
end
# Don't restore these values:
skip_nodes = %w|id workspace-id artifacts|
next if skip_nodes.member? node_name
report_info[node_name.parameterize.underscore.to_sym] = node_value
end
# Use current workspace
report_info[:workspace_id] = args[:wspace].id
# Create report, need new ID to record artifacts
report_id = report_report(report_info)
# Handle artifacts
report.elements['artifacts'].elements.each do |artifact|
artifact_opts = {}
artifact.elements.each do |attr|
skip_nodes = %w|id accessed-at|
next if skip_nodes.member? attr.name
symboled_attr = attr.name.parameterize.underscore.to_sym
artifact_opts[symboled_attr] = attr.text
end
# Use new Report as parent
artifact_opts[:report_id] = report_id
# Update to full path
artifact_opts[:file_path].gsub!(/^\./, tmp)
report_artifact(artifact_opts)
end
end
# Convert the string "NULL" to actual nil