Class: Archive::Zip::Entry::File

Inherits:
Object
  • Object
show all
Includes:
Archive::Zip::Entry
Defined in:
lib/archive/zip/entry.rb

Overview

Archive::Zip::Entry::File represents a file entry within a Zip archive.

Constant Summary

Constants included from Archive::Zip::Entry

FLAG_DATA_DESCRIPTOR_FOLLOWS, FLAG_ENCRYPTED

Instance Attribute Summary collapse

Attributes included from Archive::Zip::Entry

#atime, #comment, #compression_codec, #encryption_codec, #expected_data_descriptor, #gid, #mode, #mtime, #password, #raw_data, #uid, #zip_path

Instance Method Summary collapse

Methods included from Archive::Zip::Entry

#add_extra_field, #directory?, #dump_central_file_record, #dump_local_file_record, expand_path, from_file, parse, #symlink?

Constructor Details

#initialize(zip_path, raw_data = nil) ⇒ File

Creates a new file entry where zip_path is the path to the entry in the ZIP archive. The Archive::Zip::Codec::Deflate codec with the default compression level set (NORMAL) is used by default for compression. raw_data, if specified, must be a readable, IO-like object containing possibly compressed/encrypted file data for the entry. It is intended to be used primarily by the Archive::Zip::Entry.parse class method.


1015
1016
1017
1018
1019
1020
# File 'lib/archive/zip/entry.rb', line 1015

def initialize(zip_path, raw_data = nil)
  super(zip_path, raw_data)
  @file_path = nil
  @file_data = nil
  @compression_codec = Zip::Codec::Deflate.new
end

Instance Attribute Details

#file_pathObject

The path to a file whose contents are to be used for uncompressed file data. This will be nil if the file_data attribute is set directly.


1048
1049
1050
# File 'lib/archive/zip/entry.rb', line 1048

def file_path
  @file_path
end

Instance Method Details

#extract(options = {}) ⇒ Object

Extracts this entry.

options is a Hash optionally containing the following:

:file_path

Specifies the path to which this entry will be extracted. Defaults to the zip path of this entry.

:permissions

When set to false (the default), POSIX mode/permission bits will be ignored. Otherwise, they will be restored if possible.

:ownerships

When set to false (the default), user and group ownerships will be ignored. On most systems, only a superuser is able to change ownerships, so setting this option to true as a regular user may have no effect.

:times

When set to false (the default), last accessed and last modified times will be ignored. Otherwise, they will be restored if possible.

Raises Archive::Zip::EntryError if the extracted file data appears corrupt.


1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
# File 'lib/archive/zip/entry.rb', line 1122

def extract(options = {})
  # Ensure that unspecified options have default values.
  file_path           = options.has_key?(:file_path) ?
                        options[:file_path].to_s :
                        @zip_path
  restore_permissions = options.has_key?(:permissions) ?
                        options[:permissions] :
                        false
  restore_ownerships  = options.has_key?(:ownerships) ?
                        options[:ownerships] :
                        false
  restore_times       = options.has_key?(:times) ?
                        options[:times] :
                        false

  # Create the containing directory tree if necessary.
  parent_dir = ::File.dirname(file_path)
  FileUtils.mkdir_p(parent_dir) unless ::File.exist?(parent_dir)

  # Dump the file contents.
  ::File.open(file_path, 'wb') do |f|
    while buffer = file_data.read(4096) do
      f.write(buffer)
    end
  end

  # Verify that the extracted data is good.
  begin
    unless expected_data_descriptor.nil? then
      expected_data_descriptor.verify(file_data.data_descriptor)
    end
  rescue => e
    raise Zip::EntryError, "`#{zip_path}': #{e.message}"
  end

  # Restore the metadata.
  ::File.chmod(mode, file_path) if restore_permissions
  ::File.chown(uid, gid, file_path) if restore_ownerships
  ::File.utime(atime, mtime, file_path) if restore_times

  # Attempt to rewind the file data back to the beginning, but ignore
  # errors.
  begin
    file_data.rewind
  rescue
    # Ignore.
  end

  nil
end

#file?Boolean

Returns true.

Returns:

  • (Boolean)

1028
1029
1030
# File 'lib/archive/zip/entry.rb', line 1028

def file?
  true
end

#file_dataObject

Returns a readable, IO-like object containing uncompressed file data.

NOTE: It is the responsibility of the user of this attribute to ensure that the #close method of the returned IO-like object is called when the object is no longer needed.


1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
# File 'lib/archive/zip/entry.rb', line 1064

def file_data
  return @file_data unless @file_data.nil? || @file_data.closed?

  unless raw_data.nil? then
    raw_data.rewind
    @file_data = compression_codec.decompressor(
      encryption_codec.decryptor(raw_data, password)
    )
  else
    if @file_path.nil? then
      simulated_raw_data = BinaryStringIO.new
    else
      simulated_raw_data = ::File.new(@file_path, 'rb')
    end
    # Ensure that the IO-like object can return a data descriptor so that
    # it's possible to verify extraction later if desired.
    @file_data = Zip::Codec::Store.new.decompressor(simulated_raw_data)
  end
  @file_data
end

#file_data=(file_data) ⇒ Object

Sets the file_data attribute of this object to file_data. file_data must be a readable, IO-like object.

NOTE: As a side effect, the file_path and raw_data attributes for this object will be set to nil.


1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
# File 'lib/archive/zip/entry.rb', line 1090

def file_data=(file_data)
  @file_path = nil
  self.raw_data = nil
  @file_data = file_data
  # Ensure that the IO-like object can return CRC32 and data size
  # information so that it's possible to verify extraction later if desired.
  unless @file_data.respond_to?(:data_descriptor) then
    @file_data = Zip::Codec::Store.new.decompressor(@file_data)
  end
  @file_data
end

#ftypeObject

Returns the file type of this entry as the symbol :file.


1023
1024
1025
# File 'lib/archive/zip/entry.rb', line 1023

def ftype
  :file
end

#mode=(mode) ⇒ Object

Overridden in order to ensure that the proper mode bits are set for a file.


1034
1035
1036
# File 'lib/archive/zip/entry.rb', line 1034

def mode=(mode)
  super(0100000 | (mode & 07777))
end

#password=(password) ⇒ Object

Sets the decryption password.


1039
1040
1041
1042
1043
1044
# File 'lib/archive/zip/entry.rb', line 1039

def password=(password)
  unless @raw_data.nil? then
    @file_data = nil
  end
  @password = password
end