Class: Minitar::Input
- Inherits:
-
Object
- Object
- Minitar::Input
- Includes:
- Enumerable
- Defined in:
- lib/minitar/input.rb
Overview
Wraps a Minitar::Reader with convenience methods and wrapped stream management; Input only works with data streams that can be rewound.
Security Notice
Constructing a Minitar::Input will use Kernel.open if the provided input is not a readable stream object. Using an untrusted value for input may allow a malicious user to execute arbitrary system commands. It is the caller’s responsibility to ensure that the input value is safe.
This notice applies to Minitar::Input.open, Minitar::Input.each_entry, and Minitar::Input.new.
Instance Attribute Summary collapse
-
#tar ⇒ Object
readonly
Returns the Reader object for direct access.
Class Method Summary collapse
-
.each_entry(input) ⇒ Object
Iterates over each entry in the provided input.
-
.open(input) ⇒ Object
With no associated block,
Input.open
is a synonym forInput.new
.
Instance Method Summary collapse
-
#close ⇒ Object
Closes both the Reader object and the wrapped data stream.
-
#closed? ⇒ Boolean
Returns false if the wrapped data stream is open.
-
#each_entry ⇒ Object
(also: #each)
When provided a block, iterates through each entry in the archive.
-
#extract_entry(destdir, entry, options = {}) ⇒ Object
Extracts the current
entry
todestdir
. -
#initialize(input) ⇒ Input
constructor
Creates a new Input object.
Constructor Details
#initialize(input) ⇒ Input
Creates a new Input object. If input
is a stream object that responds to #read, then it will simply be wrapped. Otherwise, one will be created and opened using Kernel#open. When Input#close is called, the stream object wrapped will be closed.
An exception will be raised if the stream that is wrapped does not support rewinding.
:call-seq:
Minitar::Input.new(io) -> input
Minitar::Input.new(path) -> input
83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/minitar/input.rb', line 83 def initialize(input) @io = if input.respond_to?(:read) input else ::Kernel.open(input, "rb") end raise Minitar::NonSeekableStream unless Minitar.seekable?(@io, :rewind) @tar = Reader.new(@io) end |
Instance Attribute Details
#tar ⇒ Object (readonly)
Returns the Reader object for direct access.
162 163 164 |
# File 'lib/minitar/input.rb', line 162 def tar @tar end |
Class Method Details
.each_entry(input) ⇒ Object
Iterates over each entry in the provided input. This wraps the common pattern of:
Minitar::Input.open(io) do |i|
inp.each do |entry|
# ...
end
end
If a block is not provided, an enumerator will be created with the same behaviour.
:call-seq:
Minitar::Input.each_entry(io) -> enumerator
Minitar::Input.each_entry(io) { |entry| block } -> obj
63 64 65 66 67 68 69 70 71 |
# File 'lib/minitar/input.rb', line 63 def self.each_entry(input) return to_enum(__method__, input) unless block_given? Input.open(input) do |stream| stream.each do |entry| yield entry end end end |
.open(input) ⇒ Object
With no associated block, Input.open
is a synonym for Input.new
.
If a block is given, the new Input will be yielded to the block as an argument and the Input object will automatically be closed when the block terminates (this also closes the wrapped stream object). The return value will be the value of the block.
:call-seq:
Minitar::Input.open(io) -> input
Minitar::Input.open(io) { |input| block } -> obj
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/minitar/input.rb', line 34 def self.open(input) stream = new(input) if block_given? # This exception context must remain, otherwise the stream closes on open even if # a block is not given. begin yield stream ensure stream.close end else stream end end |
Instance Method Details
#close ⇒ Object
Closes both the Reader object and the wrapped data stream.
165 166 167 168 |
# File 'lib/minitar/input.rb', line 165 def close @io.close @tar.close end |
#closed? ⇒ Boolean
Returns false if the wrapped data stream is open.
159 |
# File 'lib/minitar/input.rb', line 159 def closed? = @io.closed? |
#each_entry ⇒ Object Also known as: each
When provided a block, iterates through each entry in the archive. When finished, rewinds to the beginning of the stream.
If not provided a block, creates an enumerator with the same semantics.
100 101 102 103 104 105 106 107 108 |
# File 'lib/minitar/input.rb', line 100 def each_entry return to_enum unless block_given? @tar.each do |entry| yield entry end ensure @tar.rewind end |
#extract_entry(destdir, entry, options = {}) ⇒ Object
Extracts the current entry
to destdir
. If a block is provided, it yields an action
Symbol, the full name of the file being extracted (name
), and a Hash of statistical information (stats
).
The action
will be one of:
:dir
-
The
entry
is a directory. :file_start
-
The
entry
is a file; the extract of the file is just beginning. :file_progress
-
Yielded every 4096 bytes during the extract of the
entry
. :file_done
-
Yielded when the
entry
is completed.
The stats
hash contains the following keys:
:current
-
The current total number of bytes read in the
entry
. :currinc
-
The current number of bytes read in this read cycle.
:entry
-
The entry being extracted; this is a Reader::EntryStream, with all methods thereof.
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/minitar/input.rb', line 130 def extract_entry(destdir, entry, = {}, &) # :yields: action, name, stats stats = { current: 0, currinc: 0, entry: entry } # extract_entry is not vulnerable to prefix '/' vulnerabilities, but it is # vulnerable to relative path directories. This code will break this vulnerability. # For this version, we are breaking relative paths HARD by throwing an exception. # # Future versions may permit relative paths as long as the file does not leave # +destdir+. # # However, squeeze consecutive '/' characters together. full_name = entry.full_name.squeeze("/") if /\.{2}(?:\/|\z)/.match?(full_name) raise SecureRelativePathError, "Path contains '..'" end if entry.directory? extract_directory(destdir, full_name, entry, stats, , &) else # it's a file extract_file(destdir, full_name, entry, stats, , &) end end |