pinch 0.0.7 → 0.0.8
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.
- data/Rakefile +1 -1
- data/lib/pinch.rb +51 -38
- data/spec/pinch_spec.rb +48 -26
- metadata +56 -31
data/Rakefile
CHANGED
data/lib/pinch.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
require 'net/
|
2
|
+
require 'net/https'
|
3
3
|
require 'zlib'
|
4
4
|
|
5
5
|
# @author Peter Hellberg
|
6
6
|
# @author Edward Patel
|
7
7
|
class Pinch
|
8
|
-
VERSION = "0.0.
|
8
|
+
VERSION = "0.0.8"
|
9
9
|
|
10
10
|
attr_reader :uri
|
11
11
|
|
@@ -82,38 +82,32 @@ private
|
|
82
82
|
|
83
83
|
raise Errno::ENOENT if file_headers[file_name].nil?
|
84
84
|
|
85
|
-
req = Net::HTTP::Get.new(uri.path)
|
86
85
|
padding = 16
|
87
86
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
padding)
|
96
|
-
|
97
|
-
res = Net::HTTP.start(uri.host, uri.port) do |http|
|
98
|
-
http.request(req)
|
99
|
-
end
|
87
|
+
offset_start = file_headers[file_name][16]
|
88
|
+
offset_end = 30 + padding +
|
89
|
+
file_headers[file_name][16] +
|
90
|
+
file_headers[file_name][8] +
|
91
|
+
file_headers[file_name][10] +
|
92
|
+
file_headers[file_name][11] +
|
93
|
+
file_headers[file_name][12]
|
100
94
|
|
95
|
+
response = fetch_data(offset_start, offset_end)
|
101
96
|
|
102
|
-
local_file_header =
|
103
|
-
file_data =
|
97
|
+
local_file_header = response.body.unpack('VvvvvvVVVvv')
|
98
|
+
file_data = response.body[30+local_file_header[9]+local_file_header[10]..-1]
|
104
99
|
|
105
100
|
if local_file_header[3] == 0
|
106
101
|
# Uncompressed file
|
107
102
|
offset = 30+local_file_header[9]+local_file_header[10]
|
108
|
-
|
103
|
+
response.body[offset..(offset+local_file_header[8]-1)]
|
109
104
|
else
|
110
105
|
# Compressed file
|
111
|
-
file_data =
|
106
|
+
file_data = response.body[30+local_file_header[9]+local_file_header[10]..-1]
|
112
107
|
Zlib::Inflate.new(-Zlib::MAX_WBITS).inflate(file_data)
|
113
108
|
end
|
114
109
|
end
|
115
110
|
|
116
|
-
|
117
111
|
def file_headers
|
118
112
|
@file_headers ||= begin
|
119
113
|
raise RuntimeError, "Couldn’t find the central directory." if central_directory.nil?
|
@@ -155,19 +149,15 @@ private
|
|
155
149
|
#16 uint32 relativeOffsetOfLocalFileHeader
|
156
150
|
|
157
151
|
@central_directory ||= begin
|
158
|
-
|
159
|
-
|
160
|
-
end_of_central_directory_record[5] +
|
161
|
-
end_of_central_directory_record[4])
|
152
|
+
offset_start = end_of_central_directory_record[5]
|
153
|
+
offset_end = end_of_central_directory_record[5] + end_of_central_directory_record[4]
|
162
154
|
|
163
|
-
|
164
|
-
http.request(req)
|
165
|
-
}
|
155
|
+
response = fetch_data(offset_start, offset_end)
|
166
156
|
|
167
|
-
if [200, 206].include?(
|
168
|
-
raise RuntimeError, "Couldn’t find the ZIP file (HTTP: #{
|
157
|
+
if [200, 206].include?(response.code)
|
158
|
+
raise RuntimeError, "Couldn’t find the ZIP file (HTTP: #{response.code})"
|
169
159
|
else
|
170
|
-
|
160
|
+
response.body
|
171
161
|
end
|
172
162
|
end
|
173
163
|
end
|
@@ -183,27 +173,50 @@ private
|
|
183
173
|
|
184
174
|
@end_of_central_directory_record ||= begin
|
185
175
|
# Retrieve a 4k of data from the end of the zip file
|
186
|
-
|
187
|
-
offset = content_length >= 4096 ? content_length-4096 : 0
|
176
|
+
offset = content_length >= 4096 ? content_length-4096 : 0
|
188
177
|
|
189
|
-
|
190
|
-
|
191
|
-
response = Net::HTTP.start(uri.host, uri.port) do |http|
|
192
|
-
http.request(request)
|
193
|
-
end
|
178
|
+
response = fetch_data(offset, content_length)
|
194
179
|
|
195
180
|
# Unpack the body into a hex string
|
196
181
|
hex = response.body.unpack("H*")[0]
|
197
182
|
|
198
183
|
# Split on the end record signature, and unpack the last one
|
199
184
|
[hex.split("504b0506").last].pack("H*").unpack("vvvvVVv")
|
185
|
+
|
186
|
+
# Skipping the hex unpack and splitting on
|
187
|
+
# PK\x05\x06 instead was for some reason slower.
|
200
188
|
end
|
201
189
|
end
|
202
190
|
|
191
|
+
##
|
192
|
+
# Get range of data from URL
|
193
|
+
def fetch_data(offset_start, offset_end)
|
194
|
+
request = Net::HTTP::Get.new(@uri.request_uri)
|
195
|
+
request.set_range(offset_start, offset_end)
|
196
|
+
|
197
|
+
prepared_connection.request(request)
|
198
|
+
end
|
199
|
+
|
200
|
+
##
|
203
201
|
# Retrieve the content length of the file
|
204
202
|
def content_length
|
205
|
-
@content_length ||=
|
203
|
+
@content_length ||= prepared_connection.start { |http|
|
206
204
|
http.head(@uri.path)
|
207
205
|
}['Content-Length'].to_i
|
208
206
|
end
|
207
|
+
|
208
|
+
##
|
209
|
+
# Prepare the connection and GET request
|
210
|
+
def prepared_connection
|
211
|
+
@prepared_connection ||= begin
|
212
|
+
http = Net::HTTP.new(@uri.host, @uri.port)
|
213
|
+
|
214
|
+
if @uri.is_a?(URI::HTTPS)
|
215
|
+
http.use_ssl = true
|
216
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
217
|
+
end
|
218
|
+
|
219
|
+
http
|
220
|
+
end
|
221
|
+
end
|
209
222
|
end
|
data/spec/pinch_spec.rb
CHANGED
@@ -1,33 +1,40 @@
|
|
1
1
|
require 'minitest/pride'
|
2
2
|
require 'minitest/autorun'
|
3
3
|
require 'minitest/spec'
|
4
|
+
require 'vcr'
|
5
|
+
|
6
|
+
VCR.config do |c|
|
7
|
+
c.allow_http_connections_when_no_cassette = true
|
8
|
+
c.cassette_library_dir = 'spec/fixtures/vcr_cassettes'
|
9
|
+
c.stub_with :fakeweb
|
10
|
+
end
|
4
11
|
|
5
12
|
require File.dirname(__FILE__) + '/../lib/pinch'
|
6
13
|
|
7
14
|
describe Pinch do
|
8
15
|
describe "when calling get on a compressed zip file" do
|
9
|
-
before do
|
10
|
-
@url = 'http://ftp.sunet.se/pub/lang/smalltalk/Squeak/current_stable/Squeak3.8-6665-full.zip'
|
11
|
-
@file = 'ReadMe.txt'
|
12
|
-
end
|
13
|
-
|
14
16
|
it "should return the contents of the file" do
|
15
|
-
|
16
|
-
|
17
|
-
|
17
|
+
VCR.use_cassette('squeak') do
|
18
|
+
@url = 'http://ftp.sunet.se/pub/lang/smalltalk/Squeak/current_stable/Squeak3.8-6665-full.zip'
|
19
|
+
@file = 'ReadMe.txt'
|
20
|
+
|
21
|
+
data = Pinch.get @url, @file
|
22
|
+
data.must_match(/Morphic graphics architecture/)
|
23
|
+
data.size.must_equal 26431
|
24
|
+
end
|
18
25
|
end
|
19
26
|
end
|
20
27
|
|
21
28
|
describe "when calling get on a zip file that is not compressed" do
|
22
|
-
before do
|
23
|
-
@url = 'http://memention.com/ericjohnson-canabalt-ios-ef43b7d.zip'
|
24
|
-
@file = 'ericjohnson-canabalt-ios-ef43b7d/README.TXT'
|
25
|
-
end
|
26
|
-
|
27
29
|
it "should return the contents of the file" do
|
28
|
-
|
29
|
-
|
30
|
-
|
30
|
+
VCR.use_cassette('canabalt') do
|
31
|
+
@url = 'http://memention.com/ericjohnson-canabalt-ios-ef43b7d.zip'
|
32
|
+
@file = 'ericjohnson-canabalt-ios-ef43b7d/README.TXT'
|
33
|
+
|
34
|
+
data = Pinch.get @url, @file
|
35
|
+
data.must_match(/Daring Escape/)
|
36
|
+
data.size.must_equal 2288
|
37
|
+
end
|
31
38
|
end
|
32
39
|
end
|
33
40
|
|
@@ -35,27 +42,42 @@ describe Pinch do
|
|
35
42
|
before do
|
36
43
|
@url = 'http://peterhellberg.github.com/pinch/test.zip'
|
37
44
|
@file = 'data.json'
|
45
|
+
@data = "{\"gem\":\"pinch\",\"authors\":[\"Peter Hellberg\",\"Edward Patel\"],\"github_url\":\"https://github.com/peterhellberg/pinch\"}\n"
|
38
46
|
end
|
39
47
|
|
40
48
|
it "should retrieve the contents of the file data.json" do
|
41
|
-
|
42
|
-
|
43
|
-
|
49
|
+
VCR.use_cassette('test_zip') do
|
50
|
+
data = Pinch.get @url, @file
|
51
|
+
data.must_equal @data
|
52
|
+
data.size.must_equal 114
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should retrieve the contents of the file data.json when passed a HTTPS url" do
|
57
|
+
VCR.use_cassette('ssl_test') do
|
58
|
+
@url = 'https://dl.dropbox.com/u/2230186/pinch_test.zip'
|
59
|
+
|
60
|
+
data = Pinch.get @url, @file
|
61
|
+
data.must_equal @data
|
62
|
+
data.size.must_equal 114
|
63
|
+
end
|
44
64
|
end
|
45
65
|
|
46
66
|
it "should contain three files" do
|
47
|
-
|
67
|
+
VCR.use_cassette('test_file_count') do
|
68
|
+
Pinch.file_list(@url).size.must_equal 3
|
69
|
+
end
|
48
70
|
end
|
49
71
|
end
|
50
72
|
|
51
73
|
describe "#file_list" do
|
52
|
-
before do
|
53
|
-
@url = 'http://memention.com/ericjohnson-canabalt-ios-ef43b7d.zip'
|
54
|
-
end
|
55
|
-
|
56
74
|
it "should return a list with all the file names in the zip" do
|
57
|
-
|
58
|
-
|
75
|
+
VCR.use_cassette('file_list') do
|
76
|
+
@url = 'http://memention.com/ericjohnson-canabalt-ios-ef43b7d.zip'
|
77
|
+
|
78
|
+
file_list = Pinch.file_list(@url)
|
79
|
+
file_list.size.must_equal 491
|
80
|
+
end
|
59
81
|
end
|
60
82
|
end
|
61
83
|
end
|
metadata
CHANGED
@@ -1,38 +1,62 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: pinch
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.7
|
3
|
+
version: !ruby/object:Gem::Version
|
5
4
|
prerelease:
|
5
|
+
version: 0.0.8
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
7
|
+
authors:
|
8
8
|
- Peter Hellberg
|
9
9
|
- Edward Patel
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
|
13
|
+
|
14
|
+
date: 2011-07-07 00:00:00 +02:00
|
14
15
|
default_executable:
|
15
|
-
dependencies:
|
16
|
-
- !ruby/object:Gem::Dependency
|
16
|
+
dependencies:
|
17
|
+
- !ruby/object:Gem::Dependency
|
17
18
|
name: minitest
|
18
|
-
|
19
|
+
prerelease: false
|
20
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
21
|
+
none: false
|
22
|
+
requirements:
|
23
|
+
- - ">="
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: "0"
|
26
|
+
type: :development
|
27
|
+
version_requirements: *id001
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: fakeweb
|
30
|
+
prerelease: false
|
31
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
19
32
|
none: false
|
20
|
-
requirements:
|
21
|
-
- -
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version:
|
33
|
+
requirements:
|
34
|
+
- - ">="
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: "0"
|
24
37
|
type: :development
|
38
|
+
version_requirements: *id002
|
39
|
+
- !ruby/object:Gem::Dependency
|
40
|
+
name: vcr
|
25
41
|
prerelease: false
|
26
|
-
|
27
|
-
|
28
|
-
|
42
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: "0"
|
48
|
+
type: :development
|
49
|
+
version_requirements: *id003
|
50
|
+
description: Pinch makes it possible to download a specific file from within a ZIP file over HTTP 1.1.
|
29
51
|
email: peter@c7.se
|
30
52
|
executables: []
|
53
|
+
|
31
54
|
extensions: []
|
32
|
-
|
55
|
+
|
56
|
+
extra_rdoc_files:
|
33
57
|
- README.rdoc
|
34
58
|
- MIT-LICENSE
|
35
|
-
files:
|
59
|
+
files:
|
36
60
|
- lib/pinch.rb
|
37
61
|
- MIT-LICENSE
|
38
62
|
- README.rdoc
|
@@ -40,34 +64,35 @@ files:
|
|
40
64
|
- .gemtest
|
41
65
|
- spec/pinch_spec.rb
|
42
66
|
has_rdoc: true
|
43
|
-
homepage:
|
44
|
-
licenses:
|
67
|
+
homepage: http://peterhellberg.github.com/pinch/
|
68
|
+
licenses:
|
45
69
|
- MIT-LICENSE
|
46
70
|
post_install_message:
|
47
|
-
rdoc_options:
|
71
|
+
rdoc_options:
|
48
72
|
- --main
|
49
73
|
- README.rdoc
|
50
74
|
- --charset=UTF-8
|
51
|
-
require_paths:
|
75
|
+
require_paths:
|
52
76
|
- lib
|
53
77
|
- lib
|
54
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
55
79
|
none: false
|
56
|
-
requirements:
|
57
|
-
- -
|
58
|
-
- !ruby/object:Gem::Version
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
59
83
|
version: 1.8.7
|
60
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
85
|
none: false
|
62
|
-
requirements:
|
63
|
-
- -
|
64
|
-
- !ruby/object:Gem::Version
|
65
|
-
version:
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: "0"
|
66
90
|
requirements: []
|
91
|
+
|
67
92
|
rubyforge_project:
|
68
93
|
rubygems_version: 1.6.2
|
69
94
|
signing_key:
|
70
95
|
specification_version: 3
|
71
96
|
summary: Retrieve a file from inside a zip file, over the network!
|
72
|
-
test_files:
|
97
|
+
test_files:
|
73
98
|
- spec/pinch_spec.rb
|