class Zip::Entry
Constants
- DEFLATED
- EFS
Language encoding flag (EFS) bit
- STORED
Attributes
comment[RW]
compressed_size[RW]
compression_method[RW]
crc[RW]
dirty[RW]
external_file_attributes[RW]
extra[RW]
follow_symlinks[RW]
fstype[RW]
gp_flags[RW]
header_signature[RW]
local_header_offset[RW]
name[RW]
restore_ownership[RW]
restore_permissions[RW]
restore_times[RW]
size[RW]
unix_gid[RW]
unix_perms[RW]
unix_uid[RW]
zipfile[RW]
Public Class Methods
new(*args)
click to toggle source
# File lib/zip/entry.rb, line 52 def initialize(*args) name = args[1] || '' check_name(name) set_default_vars_values @fstype = ::Zip::RUNNING_ON_WINDOWS ? ::Zip::FSTYPE_FAT : ::Zip::FSTYPE_UNIX @zipfile = args[0] || '' @name = name @comment = args[2] || '' @extra = args[3] || '' @compressed_size = args[4] || 0 @crc = args[5] || 0 @compression_method = args[6] || ::Zip::Entry::DEFLATED @size = args[7] || 0 @time = args[8] || ::Zip::DOSTime.now @ftype = name_is_directory? ? :directory : :file @extra = ::Zip::ExtraField.new(@extra.to_s) unless @extra.is_a?(::Zip::ExtraField) end
read_local_entry(io)
click to toggle source
# File lib/zip/entry.rb, line 191 def read_local_entry(io) entry = new(io) entry.read_local_entry(io) entry rescue Error nil end
Public Instance Methods
<=>(other)
click to toggle source
# File lib/zip/entry.rb, line 467 def <=>(other) to_s <=> other.to_s end
==(other)
click to toggle source
# File lib/zip/entry.rb, line 458 def ==(other) return false unless other.class == self.class # Compares contents of local entry and exposed fields keys_equal = %w(compression_method crc compressed_size size name extra filepath).all? do |k| other.__send__(k.to_sym) == __send__(k.to_sym) end keys_equal && time.dos_equals(other.time) end
check_c_dir_entry_comment_size()
click to toggle source
# File lib/zip/entry.rb, line 341 def check_c_dir_entry_comment_size return if @comment && @comment.bytesize == @comment_length raise ::Zip::Error, 'Truncated cdir zip entry header' end
check_c_dir_entry_signature()
click to toggle source
# File lib/zip/entry.rb, line 336 def check_c_dir_entry_signature return if header_signature == ::Zip::CENTRAL_DIRECTORY_ENTRY_SIGNATURE raise Error, "Zip local header magic not found at location '#{local_header_offset}'" end
check_c_dir_entry_static_header_length(buf)
click to toggle source
# File lib/zip/entry.rb, line 331 def check_c_dir_entry_static_header_length(buf) return if buf.bytesize == ::Zip::CDIR_ENTRY_STATIC_HEADER_LENGTH raise Error, 'Premature end of file. Not enough data for zip cdir entry header' end
check_name(name)
click to toggle source
# File lib/zip/entry.rb, line 47 def check_name(name) return unless name.start_with?('/') raise ::Zip::EntryNameError, "Illegal ZipEntry name '#{name}', name must not start with /" end
clean_up()
click to toggle source
# File lib/zip/entry.rb, line 558 def clean_up # By default, do nothing end
comment_size()
click to toggle source
# File lib/zip/entry.rb, line 123 def comment_size @comment ? @comment.bytesize : 0 end
extra_size()
click to toggle source
# File lib/zip/entry.rb, line 119 def extra_size @extra ? @extra.local_size : 0 end
extract(dest_path = @name, &block)
click to toggle source
Extracts entry to file dest_path (defaults to @name).
# File lib/zip/entry.rb, line 149 def extract(dest_path = @name, &block) block ||= proc { ::Zip.on_exists_proc } if directory? || file? || symlink? __send__("create_#{@ftype}", dest_path, &block) else raise "unknown file type #{inspect}" end self end
file_type_is?(type)
click to toggle source
# File lib/zip/entry.rb, line 95 def file_type_is?(type) raise InternalError, "current filetype is unknown: #{inspect}" unless @ftype @ftype == type end
get_input_stream() { |NullInputStream| ... }
click to toggle source
Returns an IO like object for the given ZipEntry. Warning: may behave weird with symlinks.
# File lib/zip/entry.rb, line 473 def get_input_stream(&block) if @ftype == :directory yield ::Zip::NullInputStream if block_given? ::Zip::NullInputStream elsif @filepath case @ftype when :file ::File.open(@filepath, 'rb', &block) when :symlink linkpath = ::File.readlink(@filepath) stringio = ::StringIO.new(linkpath) yield(stringio) if block_given? stringio else raise "unknown @file_type #{@ftype}" end else zis = ::Zip::InputStream.new(@zipfile, local_header_offset) zis.instance_variable_set(:@internal, true) zis.get_next_entry if block_given? begin yield(zis) ensure zis.close end else zis end end end
get_raw_input_stream() { |zipfile| ... }
click to toggle source
# File lib/zip/entry.rb, line 550 def get_raw_input_stream(&block) if @zipfile.respond_to?(:seek) && @zipfile.respond_to?(:read) yield @zipfile else ::File.open(@zipfile, 'rb', &block) end end
name_size()
click to toggle source
# File lib/zip/entry.rb, line 115 def name_size @name ? @name.bytesize : 0 end
pack_c_dir_entry()
click to toggle source
# File lib/zip/entry.rb, line 403 def pack_c_dir_entry zip64 = @extra['Zip64'] [ @header_signature, @version, # version of encoding software @fstype, # filesystem type @version_needed_to_extract, # @versionNeededToExtract , @gp_flags, # @gp_flags , @compression_method, @time.to_binary_dos_time, # @last_mod_time , @time.to_binary_dos_date, # @last_mod_date , @crc, (zip64 && zip64.compressed_size) ? 0xFFFFFFFF : @compressed_size, (zip64 && zip64.original_size) ? 0xFFFFFFFF : @size, name_size, @extra ? @extra.c_dir_size : 0, comment_size, (zip64 && zip64.disk_start_number) ? 0xFFFF : 0, # disk number start @internal_file_attributes, # file type (binary=0, text=1) @external_file_attributes, # native filesystem attributes (zip64 && zip64.relative_header_offset) ? 0xFFFFFFFF : @local_header_offset, @name, @extra, @comment ].pack('VCCvvvvvVVVvvvvvVV') end
pack_local_entry()
click to toggle source
# File lib/zip/entry.rb, line 251 def pack_local_entry zip64 = @extra['Zip64'] [::Zip::LOCAL_ENTRY_SIGNATURE, @version_needed_to_extract, # version needed to extract @gp_flags, # @gp_flags , @compression_method, @time.to_binary_dos_time, # @last_mod_time , @time.to_binary_dos_date, # @last_mod_date , @crc, (zip64 && zip64.compressed_size) ? 0xFFFFFFFF : @compressed_size, (zip64 && zip64.original_size) ? 0xFFFFFFFF : @size, name_size, @extra ? @extra.local_size : 0].pack('VvvvvvVVVvv') end
parent_as_string()
click to toggle source
# File lib/zip/entry.rb, line 544 def parent_as_string entry_name = name.chomp('/') slash_index = entry_name.rindex('/') slash_index ? entry_name.slice(0, slash_index + 1) : nil end
read_c_dir_extra_field(io)
click to toggle source
# File lib/zip/entry.rb, line 346 def read_c_dir_extra_field(io) if @extra.is_a?(::Zip::ExtraField) @extra.merge(io.read(@extra_length)) else @extra = ::Zip::ExtraField.new(io.read(@extra_length)) end end
set_default_vars_values()
click to toggle source
# File lib/zip/entry.rb, line 16 def set_default_vars_values @local_header_offset = 0 @local_header_size = nil # not known until local entry is created or read @internal_file_attributes = 1 @external_file_attributes = 0 @header_signature = ::Zip::CENTRAL_DIRECTORY_ENTRY_SIGNATURE @version_needed_to_extract = VERSION_NEEDED_TO_EXTRACT @version = VERSION_MADE_BY @ftype = nil # unspecified or unknown @filepath = nil @gp_flags = 0 if ::Zip.unicode_names @gp_flags |= EFS @version = 63 end @follow_symlinks = false @restore_times = true @restore_permissions = false @restore_ownership = false # BUG: need an extra field to support uid/gid's @unix_uid = nil @unix_gid = nil @unix_perms = nil # @posix_acl = nil # @ntfs_acl = nil @dirty = false end
set_ftype_from_c_dir_entry()
click to toggle source
# File lib/zip/entry.rb, line 302 def set_ftype_from_c_dir_entry @ftype = case @fstype when ::Zip::FSTYPE_UNIX @unix_perms = (@external_file_attributes >> 16) & 07777 case (@external_file_attributes >> 28) when ::Zip::FILE_TYPE_DIR :directory when ::Zip::FILE_TYPE_FILE :file when ::Zip::FILE_TYPE_SYMLINK :symlink else # best case guess for whether it is a file or not # Otherwise this would be set to unknown and that entry would never be able to extracted if name_is_directory? :directory else :file end end else if name_is_directory? :directory else :file end end end
set_unix_permissions_on_path(dest_path)
click to toggle source
# File lib/zip/entry.rb, line 384 def set_unix_permissions_on_path(dest_path) # BUG: does not update timestamps into account # ignore setuid/setgid bits by default. honor if @restore_ownership unix_perms_mask = 01777 unix_perms_mask = 07777 if @restore_ownership ::FileUtils.chmod(@unix_perms & unix_perms_mask, dest_path) if @restore_permissions && @unix_perms ::FileUtils.chown(@unix_uid, @unix_gid, dest_path) if @restore_ownership && @unix_uid && @unix_gid && ::Process.egid == 0 # File::utimes() end
time()
click to toggle source
# File lib/zip/entry.rb, line 73 def time if @extra['UniversalTime'] @extra['UniversalTime'].mtime elsif @extra['NTFS'] @extra['NTFS'].mtime else # Standard time field in central directory has local time # under archive creator. Then, we can't get timezone. @time end end
Also aliased as: mtime
time=(value)
click to toggle source
# File lib/zip/entry.rb, line 87 def time=(value) unless @extra.member?('UniversalTime') || @extra.member?('NTFS') @extra.create('UniversalTime') end (@extra['UniversalTime'] || @extra['NTFS']).mtime = value @time = value end
to_s()
click to toggle source
# File lib/zip/entry.rb, line 161 def to_s @name end
unpack_c_dir_entry(buf)
click to toggle source
# File lib/zip/entry.rb, line 278 def unpack_c_dir_entry(buf) @header_signature, @version, # version of encoding software @fstype, # filesystem type @version_needed_to_extract, @gp_flags, @compression_method, @last_mod_time, @last_mod_date, @crc, @compressed_size, @size, @name_length, @extra_length, @comment_length, _, # diskNumberStart @internal_file_attributes, @external_file_attributes, @local_header_offset, @name, @extra, @comment = buf.unpack('VCCvvvvvVVVvvvvvVV') end
unpack_local_entry(buf)
click to toggle source
# File lib/zip/entry.rb, line 202 def unpack_local_entry(buf) @header_signature, @version, @fstype, @gp_flags, @compression_method, @last_mod_time, @last_mod_date, @crc, @compressed_size, @size, @name_length, @extra_length = buf.unpack('VCCvvvvVVVvv') end
verify_local_header_size!()
click to toggle source
check before rewriting an entry (after file sizes are known) that we didn't change the header size (and thus clobber file data or something)
# File lib/zip/entry.rb, line 133 def verify_local_header_size! return if @local_header_size.nil? new_size = calculate_local_header_size raise Error, "local header size changed (#{@local_header_size} -> #{new_size})" if @local_header_size != new_size end
Private Instance Methods
create_directory(dest_path) { |self, dest_path| ... }
click to toggle source
# File lib/zip/entry.rb, line 587 def create_directory(dest_path) return if ::File.directory?(dest_path) if ::File.exist?(dest_path) if block_given? && yield(self, dest_path) ::FileUtils.rm_f dest_path else raise ::Zip::DestinationFileExistsError, "Cannot create directory '#{dest_path}'. " 'A file already exists with that name' end end ::FileUtils.mkdir_p(dest_path) set_extra_attributes_on_path(dest_path) end
create_file(dest_path, _continue_on_exists_proc = proc { Zip.continue_on_exists_proc }) { |self, dest_path| ... }
click to toggle source
# File lib/zip/entry.rb, line 570 def create_file(dest_path, _continue_on_exists_proc = proc { Zip.continue_on_exists_proc }) if ::File.exist?(dest_path) && !yield(self, dest_path) raise ::Zip::DestinationFileExistsError, "Destination '#{dest_path}' already exists" end ::File.open(dest_path, 'wb') do |os| get_input_stream do |is| set_extra_attributes_on_path(dest_path) buf = '' while (buf = is.sysread(::Zip::Decompressor::CHUNK_SIZE, buf)) os << buf end end end end
create_symlink(dest_path)
click to toggle source
BUG: #create_symlink() does not use &block
# File lib/zip/entry.rb, line 603 def create_symlink(dest_path) stat = nil begin stat = ::File.lstat(dest_path) rescue Errno::ENOENT end io = get_input_stream linkto = io.read if stat if stat.symlink? if ::File.readlink(dest_path) == linkto return else raise ::Zip::DestinationFileExistsError, "Cannot create symlink '#{dest_path}'. " 'A symlink already exists with that name' end else raise ::Zip::DestinationFileExistsError, "Cannot create symlink '#{dest_path}'. " 'A file already exists with that name' end end ::File.symlink(linkto, dest_path) end
data_descriptor_size()
click to toggle source
# File lib/zip/entry.rb, line 643 def data_descriptor_size (@gp_flags & 0x0008) > 0 ? 16 : 0 end
set_time(binary_dos_date, binary_dos_time)
click to toggle source
# File lib/zip/entry.rb, line 564 def set_time(binary_dos_date, binary_dos_time) @time = ::Zip::DOSTime.parse_binary_dos_format(binary_dos_date, binary_dos_time) rescue ArgumentError warn 'Invalid date/time in zip entry' if ::Zip.warn_invalid_date end