http_zip 1.0.0 → 2.1.0
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.
- checksums.yaml +4 -4
- data/.gitignore +3 -1
- data/CHANGELOG.md +8 -0
- data/Gemfile +1 -1
- data/README.md +1 -5
- data/Rakefile +5 -5
- data/http_zip.gemspec +21 -21
- data/lib/http_zip/compression/deflate.rb +20 -0
- data/lib/http_zip/compression/stored.rb +14 -0
- data/lib/http_zip/entry.rb +17 -32
- data/lib/http_zip/errors.rb +5 -1
- data/lib/http_zip/file.rb +2 -2
- data/lib/http_zip/parser/central_directory.rb +9 -9
- data/lib/http_zip/parser/central_directory_file_header.rb +7 -7
- data/lib/http_zip/range_request.rb +28 -37
- data/lib/http_zip/version.rb +1 -1
- data/lib/http_zip.rb +9 -7
- metadata +42 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 19b6d04b94e6807748d28eaa6efd8fea800ffa3954483f6054d9a72ffc33c5d6
|
4
|
+
data.tar.gz: 43616195f5b74a786b384757a5cad9ee0928dc7b9b13ec7f43294abe036a1f33
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b4f9b7fccbefa2a04bb61a7127ac70fad27129f58b0bbe0a7081e4e175359272de6f4db2ec98fc73887adfe34b339823b13606a3f9dc9afe9df7cba932fe4d4
|
7
|
+
data.tar.gz: f280e3fcb4fef1c70a83e80ed09916eea48a6918a3055b41b099b88365dcd2a569e516a1cb86b9b56a9e35ee414b02aece303796f3c4da47e3eef476a03673d0
|
data/.gitignore
CHANGED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
# 2.0.0
|
2
|
+
* Drop dependency on HTTParty
|
3
|
+
* Remove `RangeRequest.server_supports_content_range?` and `RangeRequest.check_server_supports_content_range!`
|
4
|
+
* Instead of pre-checking for Range request support, we just attempt the request and abort it early if the server doesn't support Range requests. This should make it more reliable for servers that e.g. don't announce support with the Accept-Ranges header or don't support HEAD requests.
|
5
|
+
* Better separation of server error responses: When the server responds with an error, HttpZip now raises `HttpZip::RequestError`. Only when the response is successful, but not `206 Partial Content`, do we raise `HttpZip::ContentRangeError`.
|
6
|
+
|
7
|
+
# 1.0.0
|
8
|
+
* Initial release
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -42,11 +42,7 @@ content = entry.read
|
|
42
42
|
entry.write_to_file('/path/extracted.txt')
|
43
43
|
```
|
44
44
|
|
45
|
-
If the server that the zip file is hosted on doesn't support Range requests, HttpZip will throw `HttpZip::ContentRangeError`.
|
46
|
-
|
47
|
-
```ruby
|
48
|
-
HttpZip::RangeRequest.server_supports_content_range?(url)
|
49
|
-
```
|
45
|
+
If the server that the zip file is hosted on doesn't support Range requests, HttpZip will throw `HttpZip::ContentRangeError`.
|
50
46
|
|
51
47
|
## Contributing
|
52
48
|
|
data/Rakefile
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "bundler/gem_tasks"
|
4
|
+
require "rake/testtask"
|
5
5
|
|
6
6
|
Rake::TestTask.new(:test) do |t|
|
7
|
-
t.libs <<
|
8
|
-
t.libs <<
|
9
|
-
t.test_files = FileList[
|
7
|
+
t.libs << "test"
|
8
|
+
t.libs << "lib"
|
9
|
+
t.test_files = FileList["test/**/*_test.rb"]
|
10
10
|
end
|
11
11
|
|
12
12
|
task default: :test
|
data/http_zip.gemspec
CHANGED
@@ -1,36 +1,36 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
lib = File.expand_path(
|
3
|
+
lib = File.expand_path("lib", __dir__)
|
4
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
-
require
|
5
|
+
require "http_zip/version"
|
6
6
|
|
7
7
|
Gem::Specification.new do |spec|
|
8
|
-
spec.name
|
9
|
-
spec.version
|
10
|
-
spec.authors
|
11
|
-
spec.email
|
8
|
+
spec.name = "http_zip"
|
9
|
+
spec.version = HttpZip::VERSION
|
10
|
+
spec.authors = ["Marvin Killing", "Peter Retzlaff"]
|
11
|
+
spec.email = ["pe.retzlaff@gmail.com"]
|
12
12
|
|
13
|
-
spec.summary
|
14
|
-
spec.homepage
|
15
|
-
spec.license
|
13
|
+
spec.summary = "HttpZip is a gem to extract individual files from a remote ZIP archive, without the need to download the entire file."
|
14
|
+
spec.homepage = "https://github.com/peret/http_zip"
|
15
|
+
spec.license = "MIT"
|
16
16
|
|
17
|
-
spec.metadata[
|
18
|
-
spec.metadata[
|
17
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
18
|
+
spec.metadata["source_code_uri"] = "https://github.com/peret/http_zip"
|
19
19
|
|
20
20
|
# Specify which files should be added to the gem when it is released.
|
21
21
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
22
22
|
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
23
23
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
24
24
|
end
|
25
|
-
spec.bindir
|
26
|
-
spec.executables
|
27
|
-
spec.require_paths = [
|
25
|
+
spec.bindir = "exe"
|
26
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
27
|
+
spec.require_paths = ["lib"]
|
28
28
|
|
29
|
-
spec.
|
30
|
-
|
31
|
-
spec.add_development_dependency
|
32
|
-
spec.add_development_dependency
|
33
|
-
spec.add_development_dependency
|
34
|
-
spec.add_development_dependency
|
35
|
-
spec.add_development_dependency
|
29
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
30
|
+
spec.add_development_dependency "minitest", "~> 5.15"
|
31
|
+
spec.add_development_dependency "rake", "~> 12.3", ">= 12.3.3"
|
32
|
+
spec.add_development_dependency "simplecov", "~> 0.21"
|
33
|
+
spec.add_development_dependency "webmock", "~> 3.14"
|
34
|
+
spec.add_development_dependency "solargraph", "~> 0.50"
|
35
|
+
spec.add_development_dependency "standard", "~> 1.31.0"
|
36
36
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module HttpZip
|
4
|
+
module Compression
|
5
|
+
class Deflate
|
6
|
+
def initialize
|
7
|
+
@inflater = Zlib::Inflate.new(-Zlib::MAX_WBITS)
|
8
|
+
end
|
9
|
+
|
10
|
+
def decompress(input)
|
11
|
+
@inflater.inflate(input)
|
12
|
+
end
|
13
|
+
|
14
|
+
def finish
|
15
|
+
@inflater.finish
|
16
|
+
@inflater.close
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/http_zip/entry.rb
CHANGED
@@ -4,13 +4,14 @@ module HttpZip
|
|
4
4
|
# Describes one entry in an HTTP zip archive
|
5
5
|
# @attr_reader [String] name filename of the entry
|
6
6
|
class Entry
|
7
|
-
attr_reader :name
|
7
|
+
attr_reader :name, :compressed_size, :uncompressed_size
|
8
8
|
|
9
|
-
def initialize(url, name, header_offset, central_directory_file_compressed_size)
|
9
|
+
def initialize(url, name, header_offset, central_directory_file_compressed_size, central_directory_file_uncompressed_size)
|
10
10
|
@range_request = HttpZip::RangeRequest.new(url)
|
11
11
|
@name = name
|
12
12
|
@header_offset = header_offset
|
13
13
|
@compressed_size = central_directory_file_compressed_size
|
14
|
+
@uncompressed_size = central_directory_file_uncompressed_size
|
14
15
|
end
|
15
16
|
|
16
17
|
# Get the decompressed content of the file entry
|
@@ -20,10 +21,9 @@ module HttpZip
|
|
20
21
|
from = @header_offset + header_size
|
21
22
|
to = @header_offset + header_size + @compressed_size
|
22
23
|
|
23
|
-
|
24
|
-
|
24
|
+
decompressor = compression_method
|
25
25
|
compressed_contents = @range_request.get(from, to)
|
26
|
-
decompress
|
26
|
+
decompressor.decompress(compressed_contents)
|
27
27
|
end
|
28
28
|
|
29
29
|
# Get the decompressed content of the file entry
|
@@ -32,14 +32,13 @@ module HttpZip
|
|
32
32
|
from = @header_offset + header_size
|
33
33
|
to = @header_offset + header_size + @compressed_size
|
34
34
|
|
35
|
-
|
36
|
-
|
37
|
-
::File.open(filename, 'wb') do |out_file|
|
35
|
+
decompressor = compression_method
|
36
|
+
::File.open(filename, "wb") do |out_file|
|
38
37
|
@range_request.get(from, to) do |chunk|
|
39
|
-
decompressed = decompress
|
38
|
+
decompressed = decompressor.decompress(chunk)
|
40
39
|
out_file.write(decompressed)
|
41
40
|
end
|
42
|
-
finish
|
41
|
+
decompressor.finish
|
43
42
|
end
|
44
43
|
end
|
45
44
|
|
@@ -52,38 +51,24 @@ module HttpZip
|
|
52
51
|
|
53
52
|
def header_size
|
54
53
|
# find out where the file contents start and how large the file is
|
55
|
-
file_name_length = header[26...28].unpack1(
|
56
|
-
extra_field_length = header[28...30].unpack1(
|
54
|
+
file_name_length = header[26...28].unpack1("v")
|
55
|
+
extra_field_length = header[28...30].unpack1("v")
|
57
56
|
30 + file_name_length + extra_field_length
|
58
57
|
end
|
59
58
|
|
60
|
-
def
|
59
|
+
def compression_method
|
61
60
|
# which compression method is used?
|
62
|
-
|
61
|
+
algorithm = header[8...10].unpack1("v")
|
63
62
|
|
64
|
-
case
|
63
|
+
case algorithm
|
65
64
|
when 0
|
66
|
-
|
67
|
-
decompress = lambda { |input|
|
68
|
-
input
|
69
|
-
}
|
70
|
-
finish = -> {}
|
65
|
+
HttpZip::Compression::Stored.new
|
71
66
|
when 8
|
72
|
-
|
73
|
-
# DEFLATED content, inflate it
|
74
|
-
decompress = lambda { |input|
|
75
|
-
inflater.inflate(input)
|
76
|
-
}
|
77
|
-
finish = lambda do
|
78
|
-
inflater.finish
|
79
|
-
inflater.close
|
80
|
-
end
|
67
|
+
HttpZip::Compression::Deflate.new
|
81
68
|
else
|
82
69
|
raise HttpZip::ZipError,
|
83
|
-
|
70
|
+
"Unsupported compression method #{algorithm}. HttpZip only supports compression methods 0 (STORED) and 8 (DEFLATE)."
|
84
71
|
end
|
85
|
-
|
86
|
-
[decompress, finish]
|
87
72
|
end
|
88
73
|
end
|
89
74
|
end
|
data/lib/http_zip/errors.rb
CHANGED
data/lib/http_zip/file.rb
CHANGED
@@ -23,7 +23,6 @@ module HttpZip
|
|
23
23
|
@url = url
|
24
24
|
@entries = nil
|
25
25
|
@range_request = RangeRequest.new(url)
|
26
|
-
@range_request.check_server_supports_content_range!
|
27
26
|
end
|
28
27
|
|
29
28
|
# Get all entries in the zip archive as an array of HttpZip::Entry.
|
@@ -43,7 +42,8 @@ module HttpZip
|
|
43
42
|
@url,
|
44
43
|
file_header.file_name,
|
45
44
|
file_header.header_offset,
|
46
|
-
file_header.compressed_size
|
45
|
+
file_header.compressed_size,
|
46
|
+
file_header.uncompressed_size
|
47
47
|
)
|
48
48
|
|
49
49
|
# skip ahead to next file entry
|
@@ -25,10 +25,10 @@ module HttpZip
|
|
25
25
|
# @raise [ZipError] if the byte stream does not contain a valid EOCD64 block
|
26
26
|
def parse_eocd64!(eocd64_block)
|
27
27
|
unless eocd64_block.start_with?(EOCD64_BLOCK_IDENTIFER)
|
28
|
-
raise ZipError,
|
28
|
+
raise ZipError, "EOCD64 record not found"
|
29
29
|
end
|
30
30
|
|
31
|
-
@size, @offset = eocd64_block[40..-1].unpack(
|
31
|
+
@size, @offset = eocd64_block[40..-1].unpack("Q<Q<")
|
32
32
|
end
|
33
33
|
|
34
34
|
private
|
@@ -40,20 +40,20 @@ module HttpZip
|
|
40
40
|
def parse!
|
41
41
|
eocd_block_index = get_eocd_block_index(@bytes)
|
42
42
|
eocd_block = @bytes[eocd_block_index..-1]
|
43
|
-
@size, @offset = eocd_block[12...20].unpack(
|
43
|
+
@size, @offset = eocd_block[12...20].unpack("VV")
|
44
44
|
return if @size != 0xFFFFFFFF && @offset != 0xFFFFFFFF
|
45
45
|
|
46
46
|
# there will be a zip64 EOCD locator block before the EOCD block
|
47
47
|
# parse the EOCD locator to find out where the EOCD64 block starts
|
48
48
|
eocd64_locator_block = @bytes[(eocd_block_index - 20)..eocd_block_index]
|
49
49
|
unless eocd64_locator_block.start_with?(EOCD64_LOCATOR_BLOCK_IDENTIFER)
|
50
|
-
raise ZipError,
|
50
|
+
raise ZipError, "Could not locate the EOCD64 locator block"
|
51
51
|
end
|
52
52
|
|
53
|
-
@eocd64_offset, total_num_disks = eocd64_locator_block[8..-1].unpack(
|
53
|
+
@eocd64_offset, total_num_disks = eocd64_locator_block[8..-1].unpack("Q<V")
|
54
54
|
return if total_num_disks == 1
|
55
55
|
|
56
|
-
raise ZipError,
|
56
|
+
raise ZipError, "Multi-disk archives are not supported"
|
57
57
|
end
|
58
58
|
|
59
59
|
# In order to find the central directory, we have to first find the EOCD block.
|
@@ -70,13 +70,13 @@ module HttpZip
|
|
70
70
|
search_end_position = candidate_eocd_block.length
|
71
71
|
loop do
|
72
72
|
eocd_block_start_index = candidate_eocd_block.rindex(EOCD_BLOCK_IDENTIFIER,
|
73
|
-
|
73
|
+
search_end_position)
|
74
74
|
|
75
|
-
raise ZipError,
|
75
|
+
raise ZipError, "Could not locate valid EOCD block" if eocd_block_start_index.nil?
|
76
76
|
|
77
77
|
# we have a candidate, verify that we found the actual eocd block start by
|
78
78
|
# checking whether its position + length matches the end of the file
|
79
|
-
comment_length = candidate_eocd_block[(eocd_block_start_index + 20)...(eocd_block_start_index + 22)].unpack1(
|
79
|
+
comment_length = candidate_eocd_block[(eocd_block_start_index + 20)...(eocd_block_start_index + 22)].unpack1("v")
|
80
80
|
if (eocd_block_start_index + 22 + comment_length) == candidate_eocd_block.length
|
81
81
|
# we found it
|
82
82
|
break
|
@@ -28,7 +28,7 @@ module HttpZip
|
|
28
28
|
def initialize(file_header_bytes)
|
29
29
|
@bytes = file_header_bytes
|
30
30
|
unless @bytes.start_with?(CENTRAL_DIRECTORY_FILE_HEADER_IDENTIFIER)
|
31
|
-
raise ZipError,
|
31
|
+
raise ZipError, "Central Directory File Header seems to be corrupt"
|
32
32
|
end
|
33
33
|
|
34
34
|
parse!
|
@@ -47,7 +47,7 @@ module HttpZip
|
|
47
47
|
@disk_number,
|
48
48
|
@internal_file_attributes,
|
49
49
|
@external_file_attributes,
|
50
|
-
@header_offset = @bytes[20...46].unpack(
|
50
|
+
@header_offset = @bytes[20...46].unpack("VVvvvvvVV")
|
51
51
|
|
52
52
|
file_name_end = 46 + file_name_length
|
53
53
|
@file_name = @bytes[46...file_name_end]
|
@@ -72,7 +72,7 @@ module HttpZip
|
|
72
72
|
# so we need to abort if there’s nothing of value in the extra fields
|
73
73
|
break if remaining_extra_field_bytes.delete("\0").empty?
|
74
74
|
|
75
|
-
record_length = remaining_extra_field_bytes[2...4].unpack1(
|
75
|
+
record_length = remaining_extra_field_bytes[2...4].unpack1("v")
|
76
76
|
|
77
77
|
# did we find the Zip64 extra field?
|
78
78
|
if remaining_extra_field_bytes.start_with?(ZIP64_EXTRA_FIELD_HEADER_ID)
|
@@ -95,19 +95,19 @@ module HttpZip
|
|
95
95
|
# so only the values too large for the non-zip64 file header will be stored here
|
96
96
|
ptr = 2 # ignore the size field, since it seems to be incorrect in some cases
|
97
97
|
if @uncompressed_size == 0xFFFFFFFF
|
98
|
-
@uncompressed_size = extra_field_bytes[ptr...(ptr + 8)].unpack1(
|
98
|
+
@uncompressed_size = extra_field_bytes[ptr...(ptr + 8)].unpack1("Q<")
|
99
99
|
ptr += 8
|
100
100
|
end
|
101
101
|
if @compressed_size == 0xFFFFFFFF
|
102
|
-
@compressed_size = extra_field_bytes[ptr...(ptr + 8)].unpack1(
|
102
|
+
@compressed_size = extra_field_bytes[ptr...(ptr + 8)].unpack1("Q<")
|
103
103
|
ptr += 8
|
104
104
|
end
|
105
105
|
if @header_offset == 0xFFFFFFFF
|
106
|
-
@header_offset = extra_field_bytes[ptr...(ptr + 8)].unpack1(
|
106
|
+
@header_offset = extra_field_bytes[ptr...(ptr + 8)].unpack1("Q<")
|
107
107
|
ptr += 8
|
108
108
|
end
|
109
109
|
if @disk_number == 0xFFFF
|
110
|
-
@disk_number = extra_field_bytes[ptr...(ptr + 4)].unpack1(
|
110
|
+
@disk_number = extra_field_bytes[ptr...(ptr + 4)].unpack1("V")
|
111
111
|
end
|
112
112
|
end
|
113
113
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "net/http"
|
4
4
|
|
5
5
|
module HttpZip
|
6
6
|
# Class to make Range requests to a HTTP server
|
@@ -9,7 +9,9 @@ module HttpZip
|
|
9
9
|
#
|
10
10
|
# @param [String] url remote file URL
|
11
11
|
def initialize(url)
|
12
|
-
@
|
12
|
+
@uri = URI(url)
|
13
|
+
@connection = Net::HTTP.new(@uri.host, @uri.port)
|
14
|
+
@connection.use_ssl = true if @uri.scheme == "https"
|
13
15
|
end
|
14
16
|
|
15
17
|
# Request a partial object via HTTP. If a block is given, yields the response body in chunks.
|
@@ -18,20 +20,10 @@ module HttpZip
|
|
18
20
|
# @param [Integer] to end byte of the range to request. Exclusive.
|
19
21
|
# @yield [chunk] yields a chunk of data to the block
|
20
22
|
# @raise [ContentRangeError] if the server responds with anything other than 206 Partial Content
|
21
|
-
def get(from, to)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
response = HTTParty.get(@url, options) do |chunk|
|
26
|
-
yield chunk if block_given?
|
27
|
-
end
|
28
|
-
|
29
|
-
if response.code != 206
|
30
|
-
# oops, we downloaded the whole file
|
31
|
-
raise ContentRangeError, 'Server does not support the Range header'
|
32
|
-
end
|
33
|
-
|
34
|
-
response.body
|
23
|
+
def get(from, to, &block)
|
24
|
+
request = Net::HTTP::Get.new(@uri)
|
25
|
+
request["Range"] = "bytes=#{from}-#{to - 1}"
|
26
|
+
make_request(request, &block)
|
35
27
|
end
|
36
28
|
|
37
29
|
# Request the last `num_bytes` bytes of the remote file via HTTP.
|
@@ -39,32 +31,31 @@ module HttpZip
|
|
39
31
|
# @param [Integer] num_bytes number of bytes to request
|
40
32
|
# @raise [ContentRangeError] if the server responds with anything other than 206 Partial Content
|
41
33
|
def last(num_bytes)
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
raise ContentRangeError, 'Server does not support the Range header'
|
46
|
-
end
|
47
|
-
|
48
|
-
response.body
|
34
|
+
request = Net::HTTP::Get.new(@uri)
|
35
|
+
request["Range"] = "bytes=-#{num_bytes}"
|
36
|
+
make_request(request)
|
49
37
|
end
|
50
38
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
39
|
+
private
|
40
|
+
|
41
|
+
def make_request(request, &block)
|
42
|
+
@connection.start do |http|
|
43
|
+
response = http.request(request) do |res|
|
44
|
+
handle_response_code!(res)
|
45
|
+
res.read_body(&block)
|
46
|
+
end
|
57
47
|
|
58
|
-
|
48
|
+
response.body unless block
|
49
|
+
end
|
59
50
|
end
|
60
51
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
52
|
+
def handle_response_code!(response)
|
53
|
+
unless response.is_a?(Net::HTTPSuccess)
|
54
|
+
raise RequestError, "Server responded with #{response.code} #{response.message}"
|
55
|
+
end
|
56
|
+
return if response.is_a?(Net::HTTPPartialContent)
|
57
|
+
|
58
|
+
raise ContentRangeError, "Server does not support the Range header"
|
68
59
|
end
|
69
60
|
end
|
70
61
|
end
|
data/lib/http_zip/version.rb
CHANGED
data/lib/http_zip.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
3
|
+
require "http_zip/version"
|
4
|
+
require "http_zip/errors"
|
5
|
+
require "http_zip/range_request"
|
6
|
+
require "http_zip/entry"
|
7
|
+
require "http_zip/file"
|
8
|
+
require "http_zip/parser/central_directory_file_header"
|
9
|
+
require "http_zip/parser/central_directory"
|
10
|
+
require "http_zip/compression/stored"
|
11
|
+
require "http_zip/compression/deflate"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: http_zip
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marvin Killing
|
@@ -9,22 +9,8 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 1980-01-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
-
- !ruby/object:Gem::Dependency
|
15
|
-
name: httparty
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
17
|
-
requirements:
|
18
|
-
- - "~>"
|
19
|
-
- !ruby/object:Gem::Version
|
20
|
-
version: '0.20'
|
21
|
-
type: :runtime
|
22
|
-
prerelease: false
|
23
|
-
version_requirements: !ruby/object:Gem::Requirement
|
24
|
-
requirements:
|
25
|
-
- - "~>"
|
26
|
-
- !ruby/object:Gem::Version
|
27
|
-
version: '0.20'
|
28
14
|
- !ruby/object:Gem::Dependency
|
29
15
|
name: bundler
|
30
16
|
requirement: !ruby/object:Gem::Requirement
|
@@ -59,14 +45,20 @@ dependencies:
|
|
59
45
|
requirements:
|
60
46
|
- - "~>"
|
61
47
|
- !ruby/object:Gem::Version
|
62
|
-
version: '
|
48
|
+
version: '12.3'
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: 12.3.3
|
63
52
|
type: :development
|
64
53
|
prerelease: false
|
65
54
|
version_requirements: !ruby/object:Gem::Requirement
|
66
55
|
requirements:
|
67
56
|
- - "~>"
|
68
57
|
- !ruby/object:Gem::Version
|
69
|
-
version: '
|
58
|
+
version: '12.3'
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 12.3.3
|
70
62
|
- !ruby/object:Gem::Dependency
|
71
63
|
name: simplecov
|
72
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -95,6 +87,34 @@ dependencies:
|
|
95
87
|
- - "~>"
|
96
88
|
- !ruby/object:Gem::Version
|
97
89
|
version: '3.14'
|
90
|
+
- !ruby/object:Gem::Dependency
|
91
|
+
name: solargraph
|
92
|
+
requirement: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.50'
|
97
|
+
type: :development
|
98
|
+
prerelease: false
|
99
|
+
version_requirements: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0.50'
|
104
|
+
- !ruby/object:Gem::Dependency
|
105
|
+
name: standard
|
106
|
+
requirement: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 1.31.0
|
111
|
+
type: :development
|
112
|
+
prerelease: false
|
113
|
+
version_requirements: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 1.31.0
|
98
118
|
description:
|
99
119
|
email:
|
100
120
|
- pe.retzlaff@gmail.com
|
@@ -104,6 +124,7 @@ extra_rdoc_files: []
|
|
104
124
|
files:
|
105
125
|
- ".gitignore"
|
106
126
|
- ".travis.yml"
|
127
|
+
- CHANGELOG.md
|
107
128
|
- Gemfile
|
108
129
|
- LICENSE.txt
|
109
130
|
- README.md
|
@@ -112,6 +133,8 @@ files:
|
|
112
133
|
- bin/setup
|
113
134
|
- http_zip.gemspec
|
114
135
|
- lib/http_zip.rb
|
136
|
+
- lib/http_zip/compression/deflate.rb
|
137
|
+
- lib/http_zip/compression/stored.rb
|
115
138
|
- lib/http_zip/entry.rb
|
116
139
|
- lib/http_zip/errors.rb
|
117
140
|
- lib/http_zip/file.rb
|
@@ -140,7 +163,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
140
163
|
- !ruby/object:Gem::Version
|
141
164
|
version: '0'
|
142
165
|
requirements: []
|
143
|
-
rubygems_version: 3.
|
166
|
+
rubygems_version: 3.5.6
|
144
167
|
signing_key:
|
145
168
|
specification_version: 4
|
146
169
|
summary: HttpZip is a gem to extract individual files from a remote ZIP archive, without
|