rack-archive-zip-extract 0.0.1
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 +7 -0
- data/lib/rack/archive/zip/extract.rb +98 -0
- metadata +128 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 9d1d1fdef39fc5a5b020441ab5e3016d4ceb278e
|
|
4
|
+
data.tar.gz: 9c122a1f1cd9c251625211a264e49ec4779fddc7
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 281a9e3aabf364311f5600e8857e579fcd2ddcccbdbb622b9bf2ccb16564bf12ec01c057660e11e5d3bb83bbd126eeda9d1892ee0218db272ddf9598dde5b5e0
|
|
7
|
+
data.tar.gz: 57c7a6d86e25a58b13b23d3d6e16c1241f2094a23de109357443a7014d140934ba2e3d967bebd2abaa06e7313f443976900acd1ea9b32c5a0ff899a08513f75b
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
require 'pathname'
|
|
2
|
+
require 'rack/utils'
|
|
3
|
+
require 'rack/file'
|
|
4
|
+
require 'rack/mime'
|
|
5
|
+
require 'zipruby'
|
|
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
|
+
module Rack::Archive
|
|
15
|
+
module Zip
|
|
16
|
+
class Extract
|
|
17
|
+
SEPS = Rack::File::SEPS
|
|
18
|
+
ALLOWED_VERBS = Rack::File::ALLOWED_VERBS
|
|
19
|
+
|
|
20
|
+
attr_reader :root
|
|
21
|
+
|
|
22
|
+
# @param root [Pathname, #to_path, String] path to document root
|
|
23
|
+
# @param extensions [Array<String>] extensions which is recognized as a zip file
|
|
24
|
+
# @raise [ArgumentError] if +root+ is not a directory
|
|
25
|
+
def initialize(root, extensions: %w[.zip])
|
|
26
|
+
@root = root.kind_of?(Pathname) ? root : Pathname(root)
|
|
27
|
+
@root = @root.expand_path
|
|
28
|
+
@extensions = extensions
|
|
29
|
+
raise ArgumentError, "Not a directory: #{@root}" unless @root.directory?
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def call(env)
|
|
33
|
+
return [405, {'Allow' => ALLOWED_VERBS.join(', ')}, []] unless ALLOWED_VERBS.include? env['REQUEST_METHOD']
|
|
34
|
+
|
|
35
|
+
path_info = Rack::Utils.unescape(env['PATH_INFO'])
|
|
36
|
+
zip_file = nil
|
|
37
|
+
body = nil
|
|
38
|
+
@extensions.each do |ext|
|
|
39
|
+
zip_file, inner_path = find_zip_file_and_inner_path(path_info, ext)
|
|
40
|
+
body = extract_content(zip_file, inner_path)
|
|
41
|
+
break if body
|
|
42
|
+
end
|
|
43
|
+
return [404, {}, []] if body.nil?
|
|
44
|
+
|
|
45
|
+
[
|
|
46
|
+
200,
|
|
47
|
+
{
|
|
48
|
+
'Content-Type' => Rack::Mime.mime_type(::File.extname(path_info)),
|
|
49
|
+
'Content-Length' => body.bytesize.to_s,
|
|
50
|
+
'Last-Modified' => zip_file.mtime.httpdate
|
|
51
|
+
},
|
|
52
|
+
[body]
|
|
53
|
+
]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# @param path_info [String]
|
|
57
|
+
# @param extension [String]
|
|
58
|
+
# @return [Array] a pair of Pathname(zip file) and String(file path in zip archive)
|
|
59
|
+
def find_zip_file_and_inner_path(path_info, extension)
|
|
60
|
+
path_parts = path_info_to_clean_parts(path_info)
|
|
61
|
+
current = @root
|
|
62
|
+
zip_file = nil
|
|
63
|
+
while part = path_parts.shift
|
|
64
|
+
zip_file = current + "#{part}#{extension}"
|
|
65
|
+
return zip_file, ::File.join(path_parts) if zip_file.file?
|
|
66
|
+
current += part
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# @param zip_file_path [Pathname] path to zip file
|
|
71
|
+
# @param inner_path [String] path to file in zip archive
|
|
72
|
+
# @return [String] content
|
|
73
|
+
# @return [nil] if +zip_file_path+ is nil or +inner_path+ is empty
|
|
74
|
+
# @return [nil] if +inner_path+ doesn't exist in zip archive
|
|
75
|
+
def extract_content(zip_file_path, inner_path)
|
|
76
|
+
return if zip_file_path.nil? or inner_path.empty?
|
|
77
|
+
::Zip::Archive.open zip_file_path.to_path do |archive|
|
|
78
|
+
return if archive.locate_name(inner_path) < 0
|
|
79
|
+
archive.fopen inner_path do |file|
|
|
80
|
+
return file.read
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# @param path_info [String]
|
|
86
|
+
# @return [Array<String>] parts of clean path
|
|
87
|
+
def path_info_to_clean_parts(path_info)
|
|
88
|
+
parts = path_info.split SEPS
|
|
89
|
+
clean = []
|
|
90
|
+
parts.each do |part|
|
|
91
|
+
next if part.empty? || part == '.'
|
|
92
|
+
part == '..' ? clean.pop : clean << part
|
|
93
|
+
end
|
|
94
|
+
clean
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: rack-archive-zip-extract
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- KITAITI Makoto
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2014-01-04 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: rack
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '1'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '1'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: zipruby
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0.3'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0.3'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: test-unit
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '1'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '1'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: test-unit-notify
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '1'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '1'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: yard
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - "~>"
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '0.8'
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - "~>"
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '0.8'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: rubygems-tasks
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - "~>"
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '0.2'
|
|
90
|
+
type: :development
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - "~>"
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '0.2'
|
|
97
|
+
description: Rack::Archive::Zip::Extract serves files in zip archives.
|
|
98
|
+
email: KitaitiMakoto@gmail.com
|
|
99
|
+
executables: []
|
|
100
|
+
extensions: []
|
|
101
|
+
extra_rdoc_files: []
|
|
102
|
+
files:
|
|
103
|
+
- lib/rack/archive/zip/extract.rb
|
|
104
|
+
homepage: https://github.com/KitaitiMakoto/rack-archive-zip-extract
|
|
105
|
+
licenses:
|
|
106
|
+
- MIT
|
|
107
|
+
metadata: {}
|
|
108
|
+
post_install_message:
|
|
109
|
+
rdoc_options: []
|
|
110
|
+
require_paths:
|
|
111
|
+
- lib
|
|
112
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
113
|
+
requirements:
|
|
114
|
+
- - ">="
|
|
115
|
+
- !ruby/object:Gem::Version
|
|
116
|
+
version: 2.0.0
|
|
117
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
118
|
+
requirements:
|
|
119
|
+
- - ">="
|
|
120
|
+
- !ruby/object:Gem::Version
|
|
121
|
+
version: '0'
|
|
122
|
+
requirements: []
|
|
123
|
+
rubyforge_project:
|
|
124
|
+
rubygems_version: 2.2.0
|
|
125
|
+
signing_key:
|
|
126
|
+
specification_version: 4
|
|
127
|
+
summary: Zip file server
|
|
128
|
+
test_files: []
|