rubyzip 1.2.1 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of rubyzip might be problematic. Click here for more details.
- checksums.yaml +4 -4
 - data/README.md +24 -17
 - data/lib/zip.rb +9 -1
 - data/lib/zip/central_directory.rb +3 -3
 - data/lib/zip/compressor.rb +1 -2
 - data/lib/zip/constants.rb +3 -3
 - data/lib/zip/crypto/null_encryption.rb +2 -4
 - data/lib/zip/decompressor.rb +1 -1
 - data/lib/zip/dos_time.rb +1 -1
 - data/lib/zip/entry.rb +46 -49
 - data/lib/zip/entry_set.rb +3 -3
 - data/lib/zip/extra_field.rb +1 -1
 - data/lib/zip/extra_field/generic.rb +1 -1
 - data/lib/zip/extra_field/zip64_placeholder.rb +1 -2
 - data/lib/zip/file.rb +12 -12
 - data/lib/zip/filesystem.rb +17 -13
 - data/lib/zip/inflater.rb +1 -1
 - data/lib/zip/input_stream.rb +10 -7
 - data/lib/zip/ioextras/abstract_input_stream.rb +1 -1
 - data/lib/zip/ioextras/abstract_output_stream.rb +1 -1
 - data/lib/zip/output_stream.rb +5 -5
 - data/lib/zip/pass_thru_decompressor.rb +1 -1
 - data/lib/zip/streamable_stream.rb +1 -1
 - data/lib/zip/version.rb +1 -1
 - data/samples/example_recursive.rb +14 -15
 - data/samples/gtk_ruby_zip.rb +1 -1
 - data/samples/qtzip.rb +1 -1
 - data/samples/zipfind.rb +2 -2
 - data/test/central_directory_entry_test.rb +1 -1
 - data/test/data/gpbit3stored.zip +0 -0
 - data/test/data/path_traversal/Makefile +10 -0
 - data/test/data/path_traversal/jwilk/README.md +5 -0
 - data/test/data/path_traversal/jwilk/absolute1.zip +0 -0
 - data/test/data/path_traversal/jwilk/absolute2.zip +0 -0
 - data/test/data/path_traversal/jwilk/dirsymlink.zip +0 -0
 - data/test/data/path_traversal/jwilk/dirsymlink2a.zip +0 -0
 - data/test/data/path_traversal/jwilk/dirsymlink2b.zip +0 -0
 - data/test/data/path_traversal/jwilk/relative0.zip +0 -0
 - data/test/data/path_traversal/jwilk/relative2.zip +0 -0
 - data/test/data/path_traversal/jwilk/symlink.zip +0 -0
 - data/test/data/path_traversal/relative1.zip +0 -0
 - data/test/data/path_traversal/tuzovakaoff/README.md +3 -0
 - data/test/data/path_traversal/tuzovakaoff/absolutepath.zip +0 -0
 - data/test/data/path_traversal/tuzovakaoff/symlink.zip +0 -0
 - data/test/data/rubycode.zip +0 -0
 - data/test/errors_test.rb +1 -0
 - data/test/file_permissions_test.rb +11 -15
 - data/test/file_test.rb +27 -9
 - data/test/filesystem/dir_iterator_test.rb +1 -1
 - data/test/filesystem/directory_test.rb +29 -11
 - data/test/filesystem/file_mutating_test.rb +3 -4
 - data/test/filesystem/file_nonmutating_test.rb +31 -31
 - data/test/filesystem/file_stat_test.rb +4 -4
 - data/test/gentestfiles.rb +13 -13
 - data/test/input_stream_test.rb +6 -6
 - data/test/ioextras/abstract_output_stream_test.rb +2 -2
 - data/test/path_traversal_test.rb +134 -0
 - data/test/test_helper.rb +2 -2
 - data/test/unicode_file_names_and_comments_test.rb +12 -0
 - data/test/zip64_full_test.rb +2 -2
 - metadata +95 -49
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA1:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 898367588fc593bddd565ee8626c75cfbcddfce2
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 24d90fd344a11d8cf3b8098c459eb2c765e933e7
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 4f00c8c74720ba3bf103596601400f57e89d03cdd90b4423debd4c96ed6150a3db0fa8f7407201657cf6a7ee0b2e6586c7a284e1398dd1cf44c523799e1b25be
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 3a434114b84d7b109e26aec4821b395ad100efda591ad004656c6b5fd8cdba3740e50c171409c726a9770996e0815ef0324c87063d975024642c6f89ba56377e
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -52,9 +52,9 @@ Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile| 
     | 
|
| 
       52 
52 
     | 
    
         
             
                # Two arguments:
         
     | 
| 
       53 
53 
     | 
    
         
             
                # - The name of the file as it will appear in the archive
         
     | 
| 
       54 
54 
     | 
    
         
             
                # - The original file, including the path to find it
         
     | 
| 
       55 
     | 
    
         
            -
                zipfile.add(filename, folder  
     | 
| 
      
 55 
     | 
    
         
            +
                zipfile.add(filename, File.join(folder, filename))
         
     | 
| 
       56 
56 
     | 
    
         
             
              end
         
     | 
| 
       57 
     | 
    
         
            -
              zipfile.get_output_stream("myFile") { | 
     | 
| 
      
 57 
     | 
    
         
            +
              zipfile.get_output_stream("myFile") { |f| f.write "myFile contains just this" }
         
     | 
| 
       58 
58 
     | 
    
         
             
            end
         
     | 
| 
       59 
59 
     | 
    
         
             
            ```
         
     | 
| 
       60 
60 
     | 
    
         | 
| 
         @@ -85,36 +85,36 @@ class ZipFileGenerator 
     | 
|
| 
       85 
85 
     | 
    
         
             
              def write
         
     | 
| 
       86 
86 
     | 
    
         
             
                entries = Dir.entries(@input_dir) - %w(. ..)
         
     | 
| 
       87 
87 
     | 
    
         | 
| 
       88 
     | 
    
         
            -
                ::Zip::File.open(@output_file, ::Zip::File::CREATE) do | 
     | 
| 
       89 
     | 
    
         
            -
                  write_entries entries, '',  
     | 
| 
      
 88 
     | 
    
         
            +
                ::Zip::File.open(@output_file, ::Zip::File::CREATE) do |zipfile|
         
     | 
| 
      
 89 
     | 
    
         
            +
                  write_entries entries, '', zipfile
         
     | 
| 
       90 
90 
     | 
    
         
             
                end
         
     | 
| 
       91 
91 
     | 
    
         
             
              end
         
     | 
| 
       92 
92 
     | 
    
         | 
| 
       93 
93 
     | 
    
         
             
              private
         
     | 
| 
       94 
94 
     | 
    
         | 
| 
       95 
95 
     | 
    
         
             
              # A helper method to make the recursion work.
         
     | 
| 
       96 
     | 
    
         
            -
              def write_entries(entries, path,  
     | 
| 
      
 96 
     | 
    
         
            +
              def write_entries(entries, path, zipfile)
         
     | 
| 
       97 
97 
     | 
    
         
             
                entries.each do |e|
         
     | 
| 
       98 
     | 
    
         
            -
                   
     | 
| 
       99 
     | 
    
         
            -
                  disk_file_path = File.join(@input_dir,  
     | 
| 
      
 98 
     | 
    
         
            +
                  zipfile_path = path == '' ? e : File.join(path, e)
         
     | 
| 
      
 99 
     | 
    
         
            +
                  disk_file_path = File.join(@input_dir, zipfile_path)
         
     | 
| 
       100 
100 
     | 
    
         
             
                  puts "Deflating #{disk_file_path}"
         
     | 
| 
       101 
101 
     | 
    
         | 
| 
       102 
102 
     | 
    
         
             
                  if File.directory? disk_file_path
         
     | 
| 
       103 
     | 
    
         
            -
                    recursively_deflate_directory(disk_file_path,  
     | 
| 
      
 103 
     | 
    
         
            +
                    recursively_deflate_directory(disk_file_path, zipfile, zipfile_path)
         
     | 
| 
       104 
104 
     | 
    
         
             
                  else
         
     | 
| 
       105 
     | 
    
         
            -
                    put_into_archive(disk_file_path,  
     | 
| 
      
 105 
     | 
    
         
            +
                    put_into_archive(disk_file_path, zipfile, zipfile_path)
         
     | 
| 
       106 
106 
     | 
    
         
             
                  end
         
     | 
| 
       107 
107 
     | 
    
         
             
                end
         
     | 
| 
       108 
108 
     | 
    
         
             
              end
         
     | 
| 
       109 
109 
     | 
    
         | 
| 
       110 
     | 
    
         
            -
              def recursively_deflate_directory(disk_file_path,  
     | 
| 
       111 
     | 
    
         
            -
                 
     | 
| 
      
 110 
     | 
    
         
            +
              def recursively_deflate_directory(disk_file_path, zipfile, zipfile_path)
         
     | 
| 
      
 111 
     | 
    
         
            +
                zipfile.mkdir zipfile_path
         
     | 
| 
       112 
112 
     | 
    
         
             
                subdir = Dir.entries(disk_file_path) - %w(. ..)
         
     | 
| 
       113 
     | 
    
         
            -
                write_entries subdir,  
     | 
| 
      
 113 
     | 
    
         
            +
                write_entries subdir, zipfile_path, zipfile
         
     | 
| 
       114 
114 
     | 
    
         
             
              end
         
     | 
| 
       115 
115 
     | 
    
         | 
| 
       116 
     | 
    
         
            -
              def put_into_archive(disk_file_path,  
     | 
| 
       117 
     | 
    
         
            -
                 
     | 
| 
      
 116 
     | 
    
         
            +
              def put_into_archive(disk_file_path, zipfile, zipfile_path)
         
     | 
| 
      
 117 
     | 
    
         
            +
                zipfile.get_output_stream(zipfile_path) do |f|
         
     | 
| 
       118 
118 
     | 
    
         
             
                  f.write(File.open(disk_file_path, 'rb').read)
         
     | 
| 
       119 
119 
     | 
    
         
             
                end
         
     | 
| 
       120 
120 
     | 
    
         
             
              end
         
     | 
| 
         @@ -175,9 +175,8 @@ end 
     | 
|
| 
       175 
175 
     | 
    
         | 
| 
       176 
176 
     | 
    
         
             
            But there is one exception when it is not working - General Purpose Flag Bit 3.
         
     | 
| 
       177 
177 
     | 
    
         | 
| 
       178 
     | 
    
         
            -
             
     | 
| 
       179 
     | 
    
         
            -
             
     | 
| 
       180 
     | 
    
         
            -
            ```
         
     | 
| 
      
 178 
     | 
    
         
            +
            > If bit 3 (0x08) of the general-purpose flags field is set, then the CRC-32 and file sizes are not known when the header is written. The fields in the local header are filled with zero, and the CRC-32 and size are appended in a 12-byte structure (optionally preceded by a 4-byte signature) immediately after the compressed data
         
     | 
| 
      
 179 
     | 
    
         
            +
             
     | 
| 
       181 
180 
     | 
    
         | 
| 
       182 
181 
     | 
    
         
             
            If `::Zip::InputStream` finds such entry in the zip archive it will raise an exception.
         
     | 
| 
       183 
182 
     | 
    
         | 
| 
         @@ -254,6 +253,14 @@ Zip.default_compression = Zlib::DEFAULT_COMPRESSION 
     | 
|
| 
       254 
253 
     | 
    
         
             
            ```
         
     | 
| 
       255 
254 
     | 
    
         
             
            It defaults to `Zlib::DEFAULT_COMPRESSION`. Possible values are `Zlib::BEST_COMPRESSION`, `Zlib::DEFAULT_COMPRESSION` and `Zlib::NO_COMPRESSION`
         
     | 
| 
       256 
255 
     | 
    
         | 
| 
      
 256 
     | 
    
         
            +
            Sometimes file names inside zip contain non-ASCII characters. If you can assume which encoding was used for such names and want to be able to find such entries using `find_entry` then you can force assumed encoding like so:
         
     | 
| 
      
 257 
     | 
    
         
            +
             
     | 
| 
      
 258 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 259 
     | 
    
         
            +
            Zip.force_entry_names_encoding = 'UTF-8'
         
     | 
| 
      
 260 
     | 
    
         
            +
            ```
         
     | 
| 
      
 261 
     | 
    
         
            +
             
     | 
| 
      
 262 
     | 
    
         
            +
            Allowed encoding names are the same as accepted by `String#force_encoding`
         
     | 
| 
      
 263 
     | 
    
         
            +
             
     | 
| 
       257 
264 
     | 
    
         
             
            You can set multiple settings at the same time by using a block:
         
     | 
| 
       258 
265 
     | 
    
         | 
| 
       259 
266 
     | 
    
         
             
            ```ruby
         
     | 
    
        data/lib/zip.rb
    CHANGED
    
    | 
         @@ -34,7 +34,15 @@ require 'zip/errors' 
     | 
|
| 
       34 
34 
     | 
    
         | 
| 
       35 
35 
     | 
    
         
             
            module Zip
         
     | 
| 
       36 
36 
     | 
    
         
             
              extend self
         
     | 
| 
       37 
     | 
    
         
            -
              attr_accessor :unicode_names, 
     | 
| 
      
 37 
     | 
    
         
            +
              attr_accessor :unicode_names,
         
     | 
| 
      
 38 
     | 
    
         
            +
                            :on_exists_proc,
         
     | 
| 
      
 39 
     | 
    
         
            +
                            :continue_on_exists_proc,
         
     | 
| 
      
 40 
     | 
    
         
            +
                            :sort_entries,
         
     | 
| 
      
 41 
     | 
    
         
            +
                            :default_compression,
         
     | 
| 
      
 42 
     | 
    
         
            +
                            :write_zip64_support,
         
     | 
| 
      
 43 
     | 
    
         
            +
                            :warn_invalid_date,
         
     | 
| 
      
 44 
     | 
    
         
            +
                            :case_insensitive_match,
         
     | 
| 
      
 45 
     | 
    
         
            +
                            :force_entry_names_encoding
         
     | 
| 
       38 
46 
     | 
    
         | 
| 
       39 
47 
     | 
    
         
             
              def reset!
         
     | 
| 
       40 
48 
     | 
    
         
             
                @_ran_once = false
         
     | 
| 
         @@ -96,7 +96,7 @@ module Zip 
     | 
|
| 
       96 
96 
     | 
    
         
             
                  @size_in_bytes                                = Entry.read_zip_64_long(buf)
         
     | 
| 
       97 
97 
     | 
    
         
             
                  @cdir_offset                                  = Entry.read_zip_64_long(buf)
         
     | 
| 
       98 
98 
     | 
    
         
             
                  @zip_64_extensible                            = buf.slice!(0, buf.bytesize)
         
     | 
| 
       99 
     | 
    
         
            -
                  raise Error, 'Zip consistency problem while reading eocd structure' unless buf. 
     | 
| 
      
 99 
     | 
    
         
            +
                  raise Error, 'Zip consistency problem while reading eocd structure' unless buf.empty?
         
     | 
| 
       100 
100 
     | 
    
         
             
                end
         
     | 
| 
       101 
101 
     | 
    
         | 
| 
       102 
102 
     | 
    
         
             
                def read_e_o_c_d(buf) #:nodoc:
         
     | 
| 
         @@ -113,7 +113,7 @@ module Zip 
     | 
|
| 
       113 
113 
     | 
    
         
             
                                                                  else
         
     | 
| 
       114 
114 
     | 
    
         
             
                                                                    buf.read(comment_length)
         
     | 
| 
       115 
115 
     | 
    
         
             
                                                                  end
         
     | 
| 
       116 
     | 
    
         
            -
                  raise Error, 'Zip consistency problem while reading eocd structure' unless buf. 
     | 
| 
      
 116 
     | 
    
         
            +
                  raise Error, 'Zip consistency problem while reading eocd structure' unless buf.empty?
         
     | 
| 
       117 
117 
     | 
    
         
             
                end
         
     | 
| 
       118 
118 
     | 
    
         | 
| 
       119 
119 
     | 
    
         
             
                def read_central_directory_entries(io) #:nodoc:
         
     | 
| 
         @@ -130,7 +130,7 @@ module Zip 
     | 
|
| 
       130 
130 
     | 
    
         | 
| 
       131 
131 
     | 
    
         
             
                def read_from_stream(io) #:nodoc:
         
     | 
| 
       132 
132 
     | 
    
         
             
                  buf = start_buf(io)
         
     | 
| 
       133 
     | 
    
         
            -
                  if  
     | 
| 
      
 133 
     | 
    
         
            +
                  if zip64_file?(buf)
         
     | 
| 
       134 
134 
     | 
    
         
             
                    read_64_e_o_c_d(buf)
         
     | 
| 
       135 
135 
     | 
    
         
             
                  else
         
     | 
| 
       136 
136 
     | 
    
         
             
                    read_e_o_c_d(buf)
         
     | 
    
        data/lib/zip/compressor.rb
    CHANGED
    
    
    
        data/lib/zip/constants.rb
    CHANGED
    
    | 
         @@ -11,9 +11,9 @@ module Zip 
     | 
|
| 
       11 
11 
     | 
    
         
             
              VERSION_NEEDED_TO_EXTRACT              = 20
         
     | 
| 
       12 
12 
     | 
    
         
             
              VERSION_NEEDED_TO_EXTRACT_ZIP64        = 45
         
     | 
| 
       13 
13 
     | 
    
         | 
| 
       14 
     | 
    
         
            -
              FILE_TYPE_FILE    =  
     | 
| 
       15 
     | 
    
         
            -
              FILE_TYPE_DIR     =  
     | 
| 
       16 
     | 
    
         
            -
              FILE_TYPE_SYMLINK =  
     | 
| 
      
 14 
     | 
    
         
            +
              FILE_TYPE_FILE    = 0o10
         
     | 
| 
      
 15 
     | 
    
         
            +
              FILE_TYPE_DIR     = 0o04
         
     | 
| 
      
 16 
     | 
    
         
            +
              FILE_TYPE_SYMLINK = 0o12
         
     | 
| 
       17 
17 
     | 
    
         | 
| 
       18 
18 
     | 
    
         
             
              FSTYPE_FAT      = 0
         
     | 
| 
       19 
19 
     | 
    
         
             
              FSTYPE_AMIGA    = 1
         
     | 
    
        data/lib/zip/decompressor.rb
    CHANGED
    
    
    
        data/lib/zip/dos_time.rb
    CHANGED
    
    
    
        data/lib/zip/entry.rb
    CHANGED
    
    | 
         @@ -99,7 +99,7 @@ module Zip 
     | 
|
| 
       99 
99 
     | 
    
         
             
                end
         
     | 
| 
       100 
100 
     | 
    
         | 
| 
       101 
101 
     | 
    
         
             
                # Dynamic checkers
         
     | 
| 
       102 
     | 
    
         
            -
                %w 
     | 
| 
      
 102 
     | 
    
         
            +
                %w[directory file symlink].each do |k|
         
     | 
| 
       103 
103 
     | 
    
         
             
                  define_method "#{k}?" do
         
     | 
| 
       104 
104 
     | 
    
         
             
                    file_type_is?(k.to_sym)
         
     | 
| 
       105 
105 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -109,6 +109,17 @@ module Zip 
     | 
|
| 
       109 
109 
     | 
    
         
             
                  @name.end_with?('/')
         
     | 
| 
       110 
110 
     | 
    
         
             
                end
         
     | 
| 
       111 
111 
     | 
    
         | 
| 
      
 112 
     | 
    
         
            +
                # Is the name a relative path, free of `..` patterns that could lead to
         
     | 
| 
      
 113 
     | 
    
         
            +
                # path traversal attacks? This does NOT handle symlinks; if the path
         
     | 
| 
      
 114 
     | 
    
         
            +
                # contains symlinks, this check is NOT enough to guarantee safety.
         
     | 
| 
      
 115 
     | 
    
         
            +
                def name_safe?
         
     | 
| 
      
 116 
     | 
    
         
            +
                  cleanpath = Pathname.new(@name).cleanpath
         
     | 
| 
      
 117 
     | 
    
         
            +
                  return false unless cleanpath.relative?
         
     | 
| 
      
 118 
     | 
    
         
            +
                  root = ::File::SEPARATOR
         
     | 
| 
      
 119 
     | 
    
         
            +
                  naive_expanded_path = ::File.join(root, cleanpath.to_s)
         
     | 
| 
      
 120 
     | 
    
         
            +
                  cleanpath.expand_path(root).to_s == naive_expanded_path
         
     | 
| 
      
 121 
     | 
    
         
            +
                end
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
       112 
123 
     | 
    
         
             
                def local_entry_offset #:nodoc:all
         
     | 
| 
       113 
124 
     | 
    
         
             
                  local_header_offset + @local_header_size
         
     | 
| 
       114 
125 
     | 
    
         
             
                end
         
     | 
| 
         @@ -147,14 +158,17 @@ module Zip 
     | 
|
| 
       147 
158 
     | 
    
         
             
                end
         
     | 
| 
       148 
159 
     | 
    
         | 
| 
       149 
160 
     | 
    
         
             
                # Extracts entry to file dest_path (defaults to @name).
         
     | 
| 
       150 
     | 
    
         
            -
                 
     | 
| 
       151 
     | 
    
         
            -
             
     | 
| 
       152 
     | 
    
         
            -
             
     | 
| 
       153 
     | 
    
         
            -
                  if  
     | 
| 
       154 
     | 
    
         
            -
                    puts "WARNING: skipped  
     | 
| 
      
 161 
     | 
    
         
            +
                # NB: The caller is responsible for making sure dest_path is safe, if it
         
     | 
| 
      
 162 
     | 
    
         
            +
                # is passed.
         
     | 
| 
      
 163 
     | 
    
         
            +
                def extract(dest_path = nil, &block)
         
     | 
| 
      
 164 
     | 
    
         
            +
                  if dest_path.nil? && !name_safe?
         
     | 
| 
      
 165 
     | 
    
         
            +
                    puts "WARNING: skipped #{@name} as unsafe"
         
     | 
| 
       155 
166 
     | 
    
         
             
                    return self
         
     | 
| 
       156 
167 
     | 
    
         
             
                  end
         
     | 
| 
       157 
168 
     | 
    
         | 
| 
      
 169 
     | 
    
         
            +
                  dest_path ||= @name
         
     | 
| 
      
 170 
     | 
    
         
            +
                  block ||= proc { ::Zip.on_exists_proc }
         
     | 
| 
      
 171 
     | 
    
         
            +
             
     | 
| 
       158 
172 
     | 
    
         
             
                  if directory? || file? || symlink?
         
     | 
| 
       159 
173 
     | 
    
         
             
                    __send__("create_#{@ftype}", dest_path, &block)
         
     | 
| 
       160 
174 
     | 
    
         
             
                  else
         
     | 
| 
         @@ -239,7 +253,10 @@ module Zip 
     | 
|
| 
       239 
253 
     | 
    
         
             
                  @name = io.read(@name_length)
         
     | 
| 
       240 
254 
     | 
    
         
             
                  extra = io.read(@extra_length)
         
     | 
| 
       241 
255 
     | 
    
         | 
| 
       242 
     | 
    
         
            -
                  @name. 
     | 
| 
      
 256 
     | 
    
         
            +
                  @name.tr!('\\', '/')
         
     | 
| 
      
 257 
     | 
    
         
            +
                  if ::Zip.force_entry_names_encoding
         
     | 
| 
      
 258 
     | 
    
         
            +
                    @name.force_encoding(::Zip.force_entry_names_encoding)
         
     | 
| 
      
 259 
     | 
    
         
            +
                  end
         
     | 
| 
       243 
260 
     | 
    
         | 
| 
       244 
261 
     | 
    
         
             
                  if extra && extra.bytesize != @extra_length
         
     | 
| 
       245 
262 
     | 
    
         
             
                    raise ::Zip::Error, 'Truncated local zip entry header'
         
     | 
| 
         @@ -263,8 +280,8 @@ module Zip 
     | 
|
| 
       263 
280 
     | 
    
         
             
                   @time.to_binary_dos_time, # @last_mod_time              ,
         
     | 
| 
       264 
281 
     | 
    
         
             
                   @time.to_binary_dos_date, # @last_mod_date              ,
         
     | 
| 
       265 
282 
     | 
    
         
             
                   @crc,
         
     | 
| 
       266 
     | 
    
         
            -
                    
     | 
| 
       267 
     | 
    
         
            -
                    
     | 
| 
      
 283 
     | 
    
         
            +
                   zip64 && zip64.compressed_size ? 0xFFFFFFFF : @compressed_size,
         
     | 
| 
      
 284 
     | 
    
         
            +
                   zip64 && zip64.original_size ? 0xFFFFFFFF : @size,
         
     | 
| 
       268 
285 
     | 
    
         
             
                   name_size,
         
     | 
| 
       269 
286 
     | 
    
         
             
                   @extra ? @extra.local_size : 0].pack('VvvvvvVVVvv')
         
     | 
| 
       270 
287 
     | 
    
         
             
                end
         
     | 
| 
         @@ -308,7 +325,7 @@ module Zip 
     | 
|
| 
       308 
325 
     | 
    
         
             
                def set_ftype_from_c_dir_entry
         
     | 
| 
       309 
326 
     | 
    
         
             
                  @ftype = case @fstype
         
     | 
| 
       310 
327 
     | 
    
         
             
                           when ::Zip::FSTYPE_UNIX
         
     | 
| 
       311 
     | 
    
         
            -
                             @unix_perms = (@external_file_attributes >> 16) &  
     | 
| 
      
 328 
     | 
    
         
            +
                             @unix_perms = (@external_file_attributes >> 16) & 0o7777
         
     | 
| 
       312 
329 
     | 
    
         
             
                             case (@external_file_attributes >> 28)
         
     | 
| 
       313 
330 
     | 
    
         
             
                             when ::Zip::FILE_TYPE_DIR
         
     | 
| 
       314 
331 
     | 
    
         
             
                               :directory
         
     | 
| 
         @@ -364,6 +381,9 @@ module Zip 
     | 
|
| 
       364 
381 
     | 
    
         
             
                  check_c_dir_entry_signature
         
     | 
| 
       365 
382 
     | 
    
         
             
                  set_time(@last_mod_date, @last_mod_time)
         
     | 
| 
       366 
383 
     | 
    
         
             
                  @name = io.read(@name_length)
         
     | 
| 
      
 384 
     | 
    
         
            +
                  if ::Zip.force_entry_names_encoding
         
     | 
| 
      
 385 
     | 
    
         
            +
                    @name.force_encoding(::Zip.force_entry_names_encoding)
         
     | 
| 
      
 386 
     | 
    
         
            +
                  end
         
     | 
| 
       367 
387 
     | 
    
         
             
                  read_c_dir_extra_field(io)
         
     | 
| 
       368 
388 
     | 
    
         
             
                  @comment = io.read(@comment_length)
         
     | 
| 
       369 
389 
     | 
    
         
             
                  check_c_dir_entry_comment_size
         
     | 
| 
         @@ -384,14 +404,14 @@ module Zip 
     | 
|
| 
       384 
404 
     | 
    
         
             
                  stat        = file_stat(path)
         
     | 
| 
       385 
405 
     | 
    
         
             
                  @unix_uid   = stat.uid
         
     | 
| 
       386 
406 
     | 
    
         
             
                  @unix_gid   = stat.gid
         
     | 
| 
       387 
     | 
    
         
            -
                  @unix_perms = stat.mode &  
     | 
| 
      
 407 
     | 
    
         
            +
                  @unix_perms = stat.mode & 0o7777
         
     | 
| 
       388 
408 
     | 
    
         
             
                end
         
     | 
| 
       389 
409 
     | 
    
         | 
| 
       390 
410 
     | 
    
         
             
                def set_unix_permissions_on_path(dest_path)
         
     | 
| 
       391 
411 
     | 
    
         
             
                  # BUG: does not update timestamps into account
         
     | 
| 
       392 
412 
     | 
    
         
             
                  # ignore setuid/setgid bits by default.  honor if @restore_ownership
         
     | 
| 
       393 
     | 
    
         
            -
                  unix_perms_mask =  
     | 
| 
       394 
     | 
    
         
            -
                  unix_perms_mask =  
     | 
| 
      
 413 
     | 
    
         
            +
                  unix_perms_mask = 0o1777
         
     | 
| 
      
 414 
     | 
    
         
            +
                  unix_perms_mask = 0o7777 if @restore_ownership
         
     | 
| 
       395 
415 
     | 
    
         
             
                  ::FileUtils.chmod(@unix_perms & unix_perms_mask, dest_path) if @restore_permissions && @unix_perms
         
     | 
| 
       396 
416 
     | 
    
         
             
                  ::FileUtils.chown(@unix_uid, @unix_gid, dest_path) if @restore_ownership && @unix_uid && @unix_gid && ::Process.egid == 0
         
     | 
| 
       397 
417 
     | 
    
         
             
                  # File::utimes()
         
     | 
| 
         @@ -418,15 +438,15 @@ module Zip 
     | 
|
| 
       418 
438 
     | 
    
         
             
                    @time.to_binary_dos_time, # @last_mod_time                      ,
         
     | 
| 
       419 
439 
     | 
    
         
             
                    @time.to_binary_dos_date, # @last_mod_date                      ,
         
     | 
| 
       420 
440 
     | 
    
         
             
                    @crc,
         
     | 
| 
       421 
     | 
    
         
            -
                     
     | 
| 
       422 
     | 
    
         
            -
                     
     | 
| 
      
 441 
     | 
    
         
            +
                    zip64 && zip64.compressed_size ? 0xFFFFFFFF : @compressed_size,
         
     | 
| 
      
 442 
     | 
    
         
            +
                    zip64 && zip64.original_size ? 0xFFFFFFFF : @size,
         
     | 
| 
       423 
443 
     | 
    
         
             
                    name_size,
         
     | 
| 
       424 
444 
     | 
    
         
             
                    @extra ? @extra.c_dir_size : 0,
         
     | 
| 
       425 
445 
     | 
    
         
             
                    comment_size,
         
     | 
| 
       426 
     | 
    
         
            -
                     
     | 
| 
      
 446 
     | 
    
         
            +
                    zip64 && zip64.disk_start_number ? 0xFFFF : 0, # disk number start
         
     | 
| 
       427 
447 
     | 
    
         
             
                    @internal_file_attributes, # file type (binary=0, text=1)
         
     | 
| 
       428 
448 
     | 
    
         
             
                    @external_file_attributes, # native filesystem attributes
         
     | 
| 
       429 
     | 
    
         
            -
                     
     | 
| 
      
 449 
     | 
    
         
            +
                    zip64 && zip64.relative_header_offset ? 0xFFFFFFFF : @local_header_offset,
         
     | 
| 
       430 
450 
     | 
    
         
             
                    @name,
         
     | 
| 
       431 
451 
     | 
    
         
             
                    @extra,
         
     | 
| 
       432 
452 
     | 
    
         
             
                    @comment
         
     | 
| 
         @@ -439,18 +459,18 @@ module Zip 
     | 
|
| 
       439 
459 
     | 
    
         
             
                  when ::Zip::FSTYPE_UNIX
         
     | 
| 
       440 
460 
     | 
    
         
             
                    ft = case @ftype
         
     | 
| 
       441 
461 
     | 
    
         
             
                         when :file
         
     | 
| 
       442 
     | 
    
         
            -
                           @unix_perms ||=  
     | 
| 
      
 462 
     | 
    
         
            +
                           @unix_perms ||= 0o644
         
     | 
| 
       443 
463 
     | 
    
         
             
                           ::Zip::FILE_TYPE_FILE
         
     | 
| 
       444 
464 
     | 
    
         
             
                         when :directory
         
     | 
| 
       445 
     | 
    
         
            -
                           @unix_perms ||=  
     | 
| 
      
 465 
     | 
    
         
            +
                           @unix_perms ||= 0o755
         
     | 
| 
       446 
466 
     | 
    
         
             
                           ::Zip::FILE_TYPE_DIR
         
     | 
| 
       447 
467 
     | 
    
         
             
                         when :symlink
         
     | 
| 
       448 
     | 
    
         
            -
                           @unix_perms ||=  
     | 
| 
      
 468 
     | 
    
         
            +
                           @unix_perms ||= 0o755
         
     | 
| 
       449 
469 
     | 
    
         
             
                           ::Zip::FILE_TYPE_SYMLINK
         
     | 
| 
       450 
470 
     | 
    
         
             
                         end
         
     | 
| 
       451 
471 
     | 
    
         | 
| 
       452 
472 
     | 
    
         
             
                    unless ft.nil?
         
     | 
| 
       453 
     | 
    
         
            -
                      @external_file_attributes = (ft << 12 | (@unix_perms &  
     | 
| 
      
 473 
     | 
    
         
            +
                      @external_file_attributes = (ft << 12 | (@unix_perms & 0o7777)) << 16
         
     | 
| 
       454 
474 
     | 
    
         
             
                    end
         
     | 
| 
       455 
475 
     | 
    
         
             
                  end
         
     | 
| 
       456 
476 
     | 
    
         | 
| 
         @@ -464,7 +484,7 @@ module Zip 
     | 
|
| 
       464 
484 
     | 
    
         
             
                def ==(other)
         
     | 
| 
       465 
485 
     | 
    
         
             
                  return false unless other.class == self.class
         
     | 
| 
       466 
486 
     | 
    
         
             
                  # Compares contents of local entry and exposed fields
         
     | 
| 
       467 
     | 
    
         
            -
                  keys_equal = %w 
     | 
| 
      
 487 
     | 
    
         
            +
                  keys_equal = %w[compression_method crc compressed_size size name extra filepath].all? do |k|
         
     | 
| 
       468 
488 
     | 
    
         
             
                    other.__send__(k.to_sym) == __send__(k.to_sym)
         
     | 
| 
       469 
489 
     | 
    
         
             
                  end
         
     | 
| 
       470 
490 
     | 
    
         
             
                  keys_equal && time.dos_equals(other.time)
         
     | 
| 
         @@ -494,7 +514,7 @@ module Zip 
     | 
|
| 
       494 
514 
     | 
    
         
             
                    end
         
     | 
| 
       495 
515 
     | 
    
         
             
                  else
         
     | 
| 
       496 
516 
     | 
    
         
             
                    zis = ::Zip::InputStream.new(@zipfile, local_header_offset)
         
     | 
| 
       497 
     | 
    
         
            -
                    zis.instance_variable_set(:@ 
     | 
| 
      
 517 
     | 
    
         
            +
                    zis.instance_variable_set(:@complete_entry, self)
         
     | 
| 
       498 
518 
     | 
    
         
             
                    zis.get_next_entry
         
     | 
| 
       499 
519 
     | 
    
         
             
                    if block_given?
         
     | 
| 
       500 
520 
     | 
    
         
             
                      begin
         
     | 
| 
         @@ -607,32 +627,9 @@ module Zip 
     | 
|
| 
       607 
627 
     | 
    
         | 
| 
       608 
628 
     | 
    
         
             
                # BUG: create_symlink() does not use &block
         
     | 
| 
       609 
629 
     | 
    
         
             
                def create_symlink(dest_path)
         
     | 
| 
       610 
     | 
    
         
            -
                   
     | 
| 
       611 
     | 
    
         
            -
                   
     | 
| 
       612 
     | 
    
         
            -
             
     | 
| 
       613 
     | 
    
         
            -
                  rescue Errno::ENOENT
         
     | 
| 
       614 
     | 
    
         
            -
                  end
         
     | 
| 
       615 
     | 
    
         
            -
             
     | 
| 
       616 
     | 
    
         
            -
                  io     = get_input_stream
         
     | 
| 
       617 
     | 
    
         
            -
                  linkto = io.read
         
     | 
| 
       618 
     | 
    
         
            -
             
     | 
| 
       619 
     | 
    
         
            -
                  if stat
         
     | 
| 
       620 
     | 
    
         
            -
                    if stat.symlink?
         
     | 
| 
       621 
     | 
    
         
            -
                      if ::File.readlink(dest_path) == linkto
         
     | 
| 
       622 
     | 
    
         
            -
                        return
         
     | 
| 
       623 
     | 
    
         
            -
                      else
         
     | 
| 
       624 
     | 
    
         
            -
                        raise ::Zip::DestinationFileExistsError,
         
     | 
| 
       625 
     | 
    
         
            -
                              "Cannot create symlink '#{dest_path}'. " \
         
     | 
| 
       626 
     | 
    
         
            -
                                  'A symlink already exists with that name'
         
     | 
| 
       627 
     | 
    
         
            -
                      end
         
     | 
| 
       628 
     | 
    
         
            -
                    else
         
     | 
| 
       629 
     | 
    
         
            -
                      raise ::Zip::DestinationFileExistsError,
         
     | 
| 
       630 
     | 
    
         
            -
                            "Cannot create symlink '#{dest_path}'. " \
         
     | 
| 
       631 
     | 
    
         
            -
                                'A file already exists with that name'
         
     | 
| 
       632 
     | 
    
         
            -
                    end
         
     | 
| 
       633 
     | 
    
         
            -
                  end
         
     | 
| 
       634 
     | 
    
         
            -
             
     | 
| 
       635 
     | 
    
         
            -
                  ::File.symlink(linkto, dest_path)
         
     | 
| 
      
 630 
     | 
    
         
            +
                  # TODO: Symlinks pose security challenges. Symlink support temporarily
         
     | 
| 
      
 631 
     | 
    
         
            +
                  # removed in view of https://github.com/rubyzip/rubyzip/issues/369 .
         
     | 
| 
      
 632 
     | 
    
         
            +
                  puts "WARNING: skipped symlink #{dest_path}"
         
     | 
| 
       636 
633 
     | 
    
         
             
                end
         
     | 
| 
       637 
634 
     | 
    
         | 
| 
       638 
635 
     | 
    
         
             
                # apply missing data from the zip64 extra information field, if present
         
     | 
    
        data/lib/zip/entry_set.rb
    CHANGED
    
    | 
         @@ -5,7 +5,7 @@ module Zip 
     | 
|
| 
       5 
5 
     | 
    
         | 
| 
       6 
6 
     | 
    
         
             
                def initialize(an_enumerable = [])
         
     | 
| 
       7 
7 
     | 
    
         
             
                  super()
         
     | 
| 
       8 
     | 
    
         
            -
                  @entry_set 
     | 
| 
      
 8 
     | 
    
         
            +
                  @entry_set = {}
         
     | 
| 
       9 
9 
     | 
    
         
             
                  an_enumerable.each { |o| push(o) }
         
     | 
| 
       10 
10 
     | 
    
         
             
                end
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
         @@ -33,9 +33,9 @@ module Zip 
     | 
|
| 
       33 
33 
     | 
    
         
             
                  entry if @entry_set.delete(to_key(entry))
         
     | 
| 
       34 
34 
     | 
    
         
             
                end
         
     | 
| 
       35 
35 
     | 
    
         | 
| 
       36 
     | 
    
         
            -
                def each 
     | 
| 
      
 36 
     | 
    
         
            +
                def each
         
     | 
| 
       37 
37 
     | 
    
         
             
                  @entry_set = sorted_entries.dup.each do |_, value|
         
     | 
| 
       38 
     | 
    
         
            -
                     
     | 
| 
      
 38 
     | 
    
         
            +
                    yield(value)
         
     | 
| 
       39 
39 
     | 
    
         
             
                  end
         
     | 
| 
       40 
40 
     | 
    
         
             
                end
         
     | 
| 
       41 
41 
     | 
    
         | 
    
        data/lib/zip/extra_field.rb
    CHANGED