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