@@ -2172,35 +2172,63 @@ def tasks(wspace=workspace)
2172
2172
end
2173
2173
2174
2174
2175
- #
2176
- # Find or create a task matching this type/data
2177
- #
2175
+ # TODO This method does not attempt to find. It just creates
2176
+ # a report based on the passed params.
2178
2177
def find_or_create_report ( opts )
2179
2178
report_report ( opts )
2180
2179
end
2181
2180
2181
+ # Creates a Report based on passed parameters. Does not handle
2182
+ # child artifacts.
2183
+ # @param opts [Hash]
2184
+ # @return [Integer] ID of created report
2182
2185
def report_report ( opts )
2183
2186
return if not active
2184
2187
::ActiveRecord ::Base . connection_pool . with_connection {
2185
- wspace = opts . delete ( :workspace ) || workspace
2186
- path = opts . delete ( :path ) || ( raise RuntimeError , "A report :path is required" )
2187
2188
2188
- ret = { }
2189
- user = opts . delete ( :user )
2190
- options = opts . delete ( :options )
2191
- rtype = opts . delete ( :rtype )
2192
- report = wspace . reports . new
2193
- report . created_by = user
2194
- report . options = options
2195
- report . rtype = rtype
2196
- report . path = path
2197
- msf_import_timestamps ( opts , report )
2198
- report . save!
2199
-
2200
- ret [ :task ] = report
2189
+ report = Report . new ( opts )
2190
+ unless report . valid?
2191
+ errors = report . errors . full_messages . join ( '; ' )
2192
+ raise RuntimeError "Report to be imported is not valid: #{ errors } "
2193
+ end
2194
+ report . state = :complete # Presume complete since it was exported
2195
+ report . save
2196
+
2197
+ report . id
2201
2198
}
2202
2199
end
2203
2200
2201
+ # Creates a ReportArtifact based on passed parameters.
2202
+ # @param opts [Hash] of ReportArtifact attributes
2203
+ def report_artifact ( opts )
2204
+ artifacts_dir = Report ::ARTIFACT_DIR
2205
+ tmp_path = opts [ :file_path ]
2206
+ artifact_name = File . basename tmp_path
2207
+ new_path = File . join ( artifacts_dir , artifact_name )
2208
+
2209
+ unless File . exists? tmp_path
2210
+ raise DBImportError 'Report artifact file to be imported does not exist.'
2211
+ end
2212
+
2213
+ unless ( File . directory? ( artifacts_dir ) && File . writable? ( artifacts_dir ) )
2214
+ raise DBImportError "Could not move report artifact file to #{ artifacts_dir } ."
2215
+ end
2216
+
2217
+ if File . exists? new_path
2218
+ unique_basename = "#{ ( Time . now . to_f *1000 ) . to_i } _#{ artifact_name } "
2219
+ new_path = File . join ( artifacts_dir , unique_basename )
2220
+ end
2221
+
2222
+ FileUtils . copy ( tmp_path , new_path )
2223
+ opts [ :file_path ] = new_path
2224
+ artifact = ReportArtifact . new ( opts )
2225
+ unless artifact . valid?
2226
+ errors = artifact . errors . full_messages . join ( '; ' )
2227
+ raise RuntimeError "Artifact to be imported is not valid: #{ errors } "
2228
+ end
2229
+ artifact . save
2230
+ end
2231
+
2204
2232
#
2205
2233
# This methods returns a list of all reports in the database
2206
2234
#
@@ -3793,43 +3821,55 @@ def import_msf_collateral(args={}, &block)
3793
3821
3794
3822
# Import Reports
3795
3823
doc . elements . each ( "/#{ btag } /reports/report" ) do |report |
3796
- tmp = args [ :ifd ] [ :zip_tmp ]
3797
- report_info = { }
3798
- report_info [ :workspace ] = args [ :wspace ]
3799
- # Should user be imported (original) or declared (the importing user)?
3800
- report_info [ :user ] = nils_for_nulls ( report . elements [ "created-by" ] . text . to_s . strip )
3801
- report_info [ :options ] = nils_for_nulls ( report . elements [ "options" ] . text . to_s . strip )
3802
- report_info [ :rtype ] = nils_for_nulls ( report . elements [ "rtype" ] . text . to_s . strip )
3803
- report_info [ :created_at ] = nils_for_nulls ( report . elements [ "created-at" ] . text . to_s . strip )
3804
- report_info [ :updated_at ] = nils_for_nulls ( report . elements [ "updated-at" ] . text . to_s . strip )
3805
- report_info [ :orig_path ] = nils_for_nulls ( report . elements [ "path" ] . text . to_s . strip )
3806
- report_info [ :task ] = args [ :task ]
3807
- report_info [ :orig_path ] . gsub! ( /^\. / , tmp ) if report_info [ :orig_path ]
3808
-
3809
- # Only report a report if we actually have it.
3810
- # TODO: Copypasta. Seperate this out.
3811
- if ::File . exists? report_info [ :orig_path ]
3812
- reports_dir = ::File . join ( basedir , "reports" )
3813
- report_file = ::File . split ( report_info [ :orig_path ] ) . last
3814
- if ::File . exists? reports_dir
3815
- unless ( ::File . directory? ( reports_dir ) && ::File . writable? ( reports_dir ) )
3816
- raise DBImportError . new ( "Could not move files to #{ reports_dir } " )
3817
- end
3818
- else
3819
- ::FileUtils . mkdir_p ( reports_dir )
3820
- end
3821
- new_report = ::File . join ( reports_dir , report_file )
3822
- report_info [ :path ] = new_report
3823
- if ::File . exists? ( new_report )
3824
- ::File . unlink new_report
3825
- else
3826
- report_report ( report_info )
3827
- end
3828
- ::FileUtils . copy ( report_info [ :orig_path ] , new_report )
3829
- yield ( :msf_report , new_report ) if block
3824
+ import_report ( report , args , basedir )
3825
+ end
3826
+ end
3827
+
3828
+ # @param report [REXML::Element] to be imported
3829
+ # @param args [Hash]
3830
+ # @param base_dir [String]
3831
+ def import_report ( report , args , base_dir )
3832
+ tmp = args [ :ifd ] [ :zip_tmp ]
3833
+ report_info = { }
3834
+
3835
+ report . elements . each do |e |
3836
+ node_name = e . name
3837
+ node_value = e . text
3838
+
3839
+ # These need to be converted back to arrays:
3840
+ array_attrs = %w| addresses file-formats options sections |
3841
+ if array_attrs . member? node_name
3842
+ node_value = JSON . parse ( node_value )
3830
3843
end
3844
+ # Don't restore these values:
3845
+ skip_nodes = %w| id workspace-id artifacts |
3846
+ next if skip_nodes . member? node_name
3847
+
3848
+ report_info [ node_name . parameterize . underscore . to_sym ] = node_value
3831
3849
end
3850
+ # Use current workspace
3851
+ report_info [ :workspace_id ] = args [ :wspace ] . id
3852
+
3853
+ # Create report, need new ID to record artifacts
3854
+ report_id = report_report ( report_info )
3832
3855
3856
+ # Handle artifacts
3857
+ report . elements [ 'artifacts' ] . elements . each do |artifact |
3858
+ artifact_opts = { }
3859
+ artifact . elements . each do |attr |
3860
+ skip_nodes = %w| id accessed-at |
3861
+ next if skip_nodes . member? attr . name
3862
+
3863
+ symboled_attr = attr . name . parameterize . underscore . to_sym
3864
+ artifact_opts [ symboled_attr ] = attr . text
3865
+ end
3866
+ # Use new Report as parent
3867
+ artifact_opts [ :report_id ] = report_id
3868
+ # Update to full path
3869
+ artifact_opts [ :file_path ] . gsub! ( /^\. / , tmp )
3870
+
3871
+ report_artifact ( artifact_opts )
3872
+ end
3833
3873
end
3834
3874
3835
3875
# Convert the string "NULL" to actual nil
0 commit comments