rack-archive-zip-extract 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/rack/archive/zip/extract.rb +59 -34
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 367946e3ae493b7beb2c8a894a737861d8819a44
|
4
|
+
data.tar.gz: 1b2509141f86cde9c02afb4ce3174136db6d57fd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0200cd1fa15c0182d6597d21dd25796c5c928753d252060a44d1255a0c10d1aa5a91ad910387321b8073e2b12773066322b06bf43dc49f705cf27e4e3ec1364d
|
7
|
+
data.tar.gz: 36807535e98a5b0947fef9066be63b5d47ad09a951854b211ea894960ddc92c61f92a1d57448a4141412e73170122a04750aa38ee4a4ce065201f874ee9e1d42
|
@@ -4,18 +4,30 @@ require 'rack/file'
|
|
4
4
|
require 'rack/mime'
|
5
5
|
require 'zipruby'
|
6
6
|
|
7
|
-
# {Rack::Archive::Zip::Extract Rack::Archive::Zip::Extract} is a Rack application which serves files in zip archives.
|
8
|
-
# @example
|
9
|
-
# run Rack::Archive::Zip::Extract.new('path/to/docroot')
|
10
|
-
# @example
|
11
|
-
# run Rack::Archive::Zip::Extract.new('path/to/docroot', extensions: %w[.epub .zip .jar .odt .docx])
|
12
|
-
# @note
|
13
|
-
# {Rack::Archive::Zip::Extract Rack::Archive::Zip::Extract} does not serve a zip file itself. Use Rack::File or so to do so.
|
14
7
|
module Rack::Archive
|
15
8
|
module Zip
|
9
|
+
# {Rack::Archive::Zip::Extract Rack::Archive::Zip::Extract} is a Rack application which serves files in zip archives.
|
10
|
+
# @example
|
11
|
+
# run Rack::Archive::Zip::Extract.new('path/to/docroot')
|
12
|
+
# @example
|
13
|
+
# run Rack::Archive::Zip::Extract.new('path/to/docroot', extensions: %w[.epub .zip .jar .odt .docx])
|
14
|
+
# @note
|
15
|
+
# {Rack::Archive::Zip::Extract Rack::Archive::Zip::Extract} does not serve a zip file itself. Use Rack::File or so to do so.
|
16
16
|
class Extract
|
17
|
+
include Rack::Utils
|
18
|
+
|
17
19
|
SEPS = Rack::File::SEPS
|
20
|
+
DOT = '.'.freeze
|
21
|
+
DOUBLE_DOT = '..'.freeze
|
22
|
+
COMMA = ','.freeze
|
18
23
|
ALLOWED_VERBS = Rack::File::ALLOWED_VERBS
|
24
|
+
ALLOW = 'Allow'.freeze
|
25
|
+
CONTENT_TYPE = 'Content-Type'.freeze
|
26
|
+
CONTENT_LENGTH = 'Content-Length'.freeze
|
27
|
+
IF_MODIFIED_SINCE = 'HTTP_IF_MODIFIED_SINCE'.freeze
|
28
|
+
LAST_MODIFIED = 'Last-Modified'.freeze
|
29
|
+
REQUEST_METHOD = 'REQUEST_METHOD'.freeze
|
30
|
+
PATH_INFO = 'PATH_INFO'.freeze
|
19
31
|
|
20
32
|
attr_reader :root
|
21
33
|
|
@@ -30,40 +42,48 @@ module Rack::Archive
|
|
30
42
|
end
|
31
43
|
|
32
44
|
def call(env)
|
33
|
-
return [
|
45
|
+
return [status_code(:method_not_allowd), {ALLOW => ALLOWED_VERBS.join(COMMA)}, []] unless ALLOWED_VERBS.include? env[REQUEST_METHOD]
|
34
46
|
|
35
|
-
path_info =
|
47
|
+
path_info = unescape(env[PATH_INFO])
|
48
|
+
if_modified_since = env[IF_MODIFIED_SINCE]
|
49
|
+
if_modified_since = Time.parse(if_modified_since) if if_modified_since
|
36
50
|
zip_file = nil
|
37
51
|
body = nil
|
52
|
+
file_size = nil
|
53
|
+
mtime = nil
|
38
54
|
@extensions.each do |ext|
|
39
55
|
zip_file, inner_path = find_zip_file_and_inner_path(path_info, ext)
|
40
|
-
body = extract_content(zip_file, inner_path)
|
41
|
-
break if
|
56
|
+
body, file_size, mtime = extract_content(zip_file, inner_path, if_modified_since)
|
57
|
+
break if mtime
|
42
58
|
end
|
43
|
-
return [
|
59
|
+
return [status_code(:not_found), {}, []] if mtime.nil?
|
44
60
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
61
|
+
if if_modified_since and mtime <= if_modified_since
|
62
|
+
[status_code(:not_modified), {}, []]
|
63
|
+
else
|
64
|
+
[
|
65
|
+
status_code(:ok),
|
66
|
+
{
|
67
|
+
CONTENT_TYPE => Rack::Mime.mime_type(::File.extname(path_info)),
|
68
|
+
CONTENT_LENGTH => file_size.to_s,
|
69
|
+
LAST_MODIFIED => mtime.httpdate
|
70
|
+
},
|
71
|
+
[body]
|
72
|
+
]
|
73
|
+
end
|
54
74
|
end
|
55
75
|
|
56
76
|
# @param path_info [String]
|
57
77
|
# @param extension [String]
|
58
78
|
# @return [Array] a pair of Pathname(zip file) and String(file path in zip archive)
|
59
79
|
def find_zip_file_and_inner_path(path_info, extension)
|
60
|
-
|
80
|
+
segments = path_info_to_clean_segments(path_info)
|
61
81
|
current = @root
|
62
82
|
zip_file = nil
|
63
|
-
while
|
64
|
-
zip_file = current + "#{
|
65
|
-
return zip_file, ::File.join(
|
66
|
-
current +=
|
83
|
+
while segment = segments.shift
|
84
|
+
zip_file = current + "#{segment}#{extension}"
|
85
|
+
return zip_file, ::File.join(segments) if zip_file.file?
|
86
|
+
current += segment
|
67
87
|
end
|
68
88
|
end
|
69
89
|
|
@@ -72,24 +92,29 @@ module Rack::Archive
|
|
72
92
|
# @return [String] content
|
73
93
|
# @return [nil] if +zip_file_path+ is nil or +inner_path+ is empty
|
74
94
|
# @return [nil] if +inner_path+ doesn't exist in zip archive
|
75
|
-
def extract_content(zip_file_path, inner_path)
|
95
|
+
def extract_content(zip_file_path, inner_path, if_modified_since)
|
76
96
|
return if zip_file_path.nil? or inner_path.empty?
|
77
97
|
::Zip::Archive.open zip_file_path.to_path do |archive|
|
78
98
|
return if archive.locate_name(inner_path) < 0
|
79
99
|
archive.fopen inner_path do |file|
|
80
|
-
|
100
|
+
if if_modified_since and file.mtime <= if_modified_since
|
101
|
+
return nil, nil, file.mtime
|
102
|
+
else
|
103
|
+
return file.read, file.size, file.mtime
|
104
|
+
end
|
81
105
|
end
|
82
106
|
end
|
83
107
|
end
|
84
108
|
|
85
109
|
# @param path_info [String]
|
86
|
-
# @return [Array<String>]
|
87
|
-
|
88
|
-
|
110
|
+
# @return [Array<String>] segments of clean path
|
111
|
+
# @see http://rubydoc.info/gems/rack/Rack/File#_call-instance_method Algorithm stolen from Rack::File#_call
|
112
|
+
def path_info_to_clean_segments(path_info)
|
113
|
+
segments = path_info.split SEPS
|
89
114
|
clean = []
|
90
|
-
|
91
|
-
next if
|
92
|
-
|
115
|
+
segments.each do |segment|
|
116
|
+
next if segment.empty? || segment == DOT
|
117
|
+
segment == DOUBLE_DOT ? clean.pop : clean << segment
|
93
118
|
end
|
94
119
|
clean
|
95
120
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-archive-zip-extract
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- KITAITI Makoto
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-01-
|
11
|
+
date: 2014-01-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|