lib/inspec/file_provider.rb in inspec-4.16.0 vs lib/inspec/file_provider.rb in inspec-4.17.7

- old
+ new

@@ -49,11 +49,11 @@ end def relative_provider RelativeFileProvider.new(self) end - end + end # class FileProvider class MockProvider < FileProvider attr_reader :files def initialize(path) @data = path[:mock] @@ -87,11 +87,11 @@ return nil unless files.include?(file) return nil unless File.file?(file) File.binread(file) end - end + end # class DirProvider class ZipProvider < FileProvider attr_reader :files def initialize(path) @@ -144,82 +144,72 @@ break end end res end - end + end # class ZipProvider class TarProvider < FileProvider attr_reader :files def initialize(path) @path = path @contents = {} - @files = [] - walk_tar(@path) do |tar| - @files = tar.find_all(&:file?) - # delete all entries with no name - @files = @files.find_all { |x| !x.full_name.empty? && x.full_name.squeeze("/") !~ %r{\.{2}(?:/|\z)} } + here = Pathname.new(".") - # delete all entries that have a PaxHeader - @files = @files.delete_if { |x| x.full_name.include?("PaxHeader/") } + walk_tar(@path) do |entries| + entries.each do |entry| + name = entry.full_name - # replace all items of the array simply with the relative filename of the file - @files.map! { |x| Pathname.new(x.full_name).relative_path_from(Pathname.new(".")).to_s } + # rubocop:disable Layout/MultilineOperationIndentation + # rubocop:disable Style/ParenthesesAroundCondition + next unless (entry.file? && # duh + !name.empty? && # for empty filenames? + name !~ %r{\.\.(?:/|\z)} && # .. (to avoid attacks?) + !name.include?("PaxHeader/")) + + path = Pathname.new(name).relative_path_from(here).to_s + + @contents[path] = begin # not ||= in a tarball, last one wins + res = entry.read + try = res.dup + try.force_encoding Encoding::UTF_8 + res = try if try.valid_encoding? + res + end + end + + @files = @contents.keys end end def extract(destination_path = ".") FileUtils.mkdir_p(destination_path) - walk_tar(@path) do |files| - files.each do |file| - next unless @files.include?(file.full_name) + @contents.each do |path, body| + full_path = File.join(destination_path, path) - final_path = File.join(destination_path, file.full_name) - - # This removes the top level directory (and any other files) to ensure - # extracted files do not conflict. - FileUtils.remove_entry(final_path) if File.exist?(final_path) - - FileUtils.mkdir_p(File.dirname(final_path)) - File.open(final_path, "wb") { |f| f.write(file.read) } - end + FileUtils.mkdir_p(File.dirname(full_path)) + File.open(full_path, "wb") { |f| f.write(body) } end end def read(file) - @contents[file] ||= read_from_tar(file) + @contents[file] end private def walk_tar(path, &callback) tar_file = Zlib::GzipReader.open(path) Gem::Package::TarReader.new(tar_file, &callback) ensure tar_file.close end + end # class TarProvider - def read_from_tar(file) - return nil unless @files.include?(file) - - res = nil - # NB `TarReader` includes `Enumerable` beginning with Ruby 2.x - walk_tar(@path) do |tar| - tar.each do |entry| - next unless entry.file? && [file, "./#{file}"].include?(entry.full_name) - - res = entry.read - break - end - end - res - end - end - class RelativeFileProvider BLACKLIST_FILES = [ "/pax_global_header", "pax_global_header", ].freeze @@ -316,7 +306,7 @@ # edge case: completely different prefixes; retry prefix detection a = File.dirname(pre + "a") b = File.dirname(new_pre + "b") get_prefix([a, b]) end - end + end # class RelativeFileProvider end