mini_mime 0.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 +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +5 -0
- data/CHANGELOG +4 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +38 -0
- data/Rakefile +80 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/db/content_type_mime.db +857 -0
- data/lib/db/ext_mime.db +1161 -0
- data/lib/mini_mime.rb +173 -0
- data/lib/mini_mime/version.rb +3 -0
- data/mini_mime.gemspec +29 -0
- metadata +115 -0
data/lib/mini_mime.rb
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
require "mini_mime/version"
|
|
2
|
+
require "thread"
|
|
3
|
+
|
|
4
|
+
module MiniMime
|
|
5
|
+
BINARY_ENCODINGS = %w(base64 8bit)
|
|
6
|
+
|
|
7
|
+
# return true if this filename is known to have binary encoding
|
|
8
|
+
#
|
|
9
|
+
# puts MiniMime.binary?("file.gif") => true
|
|
10
|
+
# puts MiniMime.binary?("file.txt") => false
|
|
11
|
+
def self.binary?(filename)
|
|
12
|
+
info = Db.lookup_by_filename(filename)
|
|
13
|
+
!!(info && BINARY_ENCODINGS.include?(info.encoding))
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# return true if this content type is known to have binary encoding
|
|
17
|
+
#
|
|
18
|
+
# puts MiniMime.binary_content_type?("text/plain") => false
|
|
19
|
+
# puts MiniMime.binary?("application/x-compress") => true
|
|
20
|
+
def self.binary_content_type?(mime)
|
|
21
|
+
info = Db.lookup_by_content_type(mime)
|
|
22
|
+
!!(info && BINARY_ENCODINGS.include?(info.encoding))
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# return first matching content type for a file
|
|
26
|
+
#
|
|
27
|
+
# puts MiniMime.content_type("test.xml") => "application/xml"
|
|
28
|
+
# puts MiniMime.content_type("test.gif") => "image/gif"
|
|
29
|
+
def self.content_type(filename)
|
|
30
|
+
info = Db.lookup_by_filename(filename)
|
|
31
|
+
info && info.content_type
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
class Info
|
|
35
|
+
attr_accessor :extension, :content_type, :encoding
|
|
36
|
+
def initialize(buffer)
|
|
37
|
+
@extension,@content_type,@encoding = buffer.split(/\s+/).map!(&:freeze)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def [](idx)
|
|
41
|
+
if idx == 0
|
|
42
|
+
@extension
|
|
43
|
+
elsif idx == 1
|
|
44
|
+
@content_type
|
|
45
|
+
elsif idx == 2
|
|
46
|
+
@encoding
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
class Db
|
|
52
|
+
LOCK = Mutex.new
|
|
53
|
+
|
|
54
|
+
def self.lookup_by_filename(filename)
|
|
55
|
+
extension = File.extname(filename)
|
|
56
|
+
if extension
|
|
57
|
+
extension.sub!(".", "")
|
|
58
|
+
extension.downcase!
|
|
59
|
+
if extension.length > 0
|
|
60
|
+
LOCK.synchronize do
|
|
61
|
+
@db ||= new
|
|
62
|
+
@db.lookup_by_extension(extension)
|
|
63
|
+
end
|
|
64
|
+
else
|
|
65
|
+
nil
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def self.lookup_by_content_type(content_type)
|
|
71
|
+
LOCK.synchronize do
|
|
72
|
+
@db ||= new
|
|
73
|
+
@db.lookup_by_content_type(content_type)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class Cache
|
|
79
|
+
def initialize(size)
|
|
80
|
+
@size = size
|
|
81
|
+
@hash = {}
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def []=(key,val)
|
|
85
|
+
rval = @hash[key] = val
|
|
86
|
+
if @hash.length > @size
|
|
87
|
+
@hash.shift
|
|
88
|
+
end
|
|
89
|
+
rval
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def fetch(key, &blk)
|
|
93
|
+
@hash.fetch(key, &blk)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
class RandomAccessDb
|
|
98
|
+
|
|
99
|
+
MAX_CACHED = 100
|
|
100
|
+
|
|
101
|
+
def initialize(name, sort_order)
|
|
102
|
+
@path = File.expand_path("../db/#{name}", __FILE__)
|
|
103
|
+
@file = File.open(@path)
|
|
104
|
+
|
|
105
|
+
@row_length = @file.readline.length
|
|
106
|
+
@file_length = @file.size
|
|
107
|
+
@rows = @file_length / @row_length
|
|
108
|
+
|
|
109
|
+
@hit_cache = Cache.new(MAX_CACHED)
|
|
110
|
+
@miss_cache = Cache.new(MAX_CACHED)
|
|
111
|
+
|
|
112
|
+
@sort_order = sort_order
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def lookup(val)
|
|
116
|
+
@hit_cache.fetch(val) do
|
|
117
|
+
@miss_cache.fetch(val) do
|
|
118
|
+
data = lookup_uncached(val)
|
|
119
|
+
if data
|
|
120
|
+
@hit_cache[val] = data
|
|
121
|
+
else
|
|
122
|
+
@miss_cache[val] = nil
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
data
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
#lifted from marcandre/backports
|
|
131
|
+
def lookup_uncached(val)
|
|
132
|
+
from = 0
|
|
133
|
+
to = @rows - 1
|
|
134
|
+
result = nil
|
|
135
|
+
|
|
136
|
+
while from <= to do
|
|
137
|
+
midpoint = from + (to-from).div(2)
|
|
138
|
+
current = resolve(midpoint)
|
|
139
|
+
data = current[@sort_order]
|
|
140
|
+
if data > val
|
|
141
|
+
to = midpoint - 1
|
|
142
|
+
elsif data < val
|
|
143
|
+
from = midpoint + 1
|
|
144
|
+
else
|
|
145
|
+
result = current
|
|
146
|
+
break
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
result
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def resolve(row)
|
|
153
|
+
@file.seek(row*@row_length)
|
|
154
|
+
Info.new(@file.readline)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def initialize
|
|
160
|
+
@ext_db = RandomAccessDb.new("ext_mime.db", 0)
|
|
161
|
+
@content_type_db = RandomAccessDb.new("content_type_mime.db", 1)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def lookup_by_extension(extension)
|
|
165
|
+
@ext_db.lookup(extension)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def lookup_by_content_type(content_type)
|
|
169
|
+
@content_type_db.lookup(content_type)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
end
|
|
173
|
+
end
|
data/mini_mime.gemspec
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
|
+
require 'mini_mime/version'
|
|
6
|
+
|
|
7
|
+
Gem::Specification.new do |spec|
|
|
8
|
+
spec.name = "mini_mime"
|
|
9
|
+
spec.version = MiniMime::VERSION
|
|
10
|
+
spec.authors = ["Sam Saffron"]
|
|
11
|
+
spec.email = ["sam.saffron@gmail.com"]
|
|
12
|
+
|
|
13
|
+
spec.summary = %q{A lightweight mime type lookup toy}
|
|
14
|
+
spec.description = %q{A lightweight mime type lookup toy}
|
|
15
|
+
spec.homepage = "https://github.com/discourse/mini_mime"
|
|
16
|
+
spec.license = "MIT"
|
|
17
|
+
|
|
18
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
|
19
|
+
f.match(%r{^(test|spec|features)/})
|
|
20
|
+
end
|
|
21
|
+
spec.bindir = "exe"
|
|
22
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
23
|
+
spec.require_paths = ["lib"]
|
|
24
|
+
|
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.13"
|
|
26
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
|
27
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
|
28
|
+
spec.add_development_dependency "mime-types", "~> 3"
|
|
29
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: mini_mime
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Sam Saffron
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2016-12-13 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: bundler
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '1.13'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '1.13'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: rake
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '10.0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '10.0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: minitest
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '5.0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '5.0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: mime-types
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '3'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '3'
|
|
69
|
+
description: A lightweight mime type lookup toy
|
|
70
|
+
email:
|
|
71
|
+
- sam.saffron@gmail.com
|
|
72
|
+
executables: []
|
|
73
|
+
extensions: []
|
|
74
|
+
extra_rdoc_files: []
|
|
75
|
+
files:
|
|
76
|
+
- ".gitignore"
|
|
77
|
+
- ".travis.yml"
|
|
78
|
+
- CHANGELOG
|
|
79
|
+
- CODE_OF_CONDUCT.md
|
|
80
|
+
- Gemfile
|
|
81
|
+
- LICENSE.txt
|
|
82
|
+
- README.md
|
|
83
|
+
- Rakefile
|
|
84
|
+
- bin/console
|
|
85
|
+
- bin/setup
|
|
86
|
+
- lib/db/content_type_mime.db
|
|
87
|
+
- lib/db/ext_mime.db
|
|
88
|
+
- lib/mini_mime.rb
|
|
89
|
+
- lib/mini_mime/version.rb
|
|
90
|
+
- mini_mime.gemspec
|
|
91
|
+
homepage: https://github.com/discourse/mini_mime
|
|
92
|
+
licenses:
|
|
93
|
+
- MIT
|
|
94
|
+
metadata: {}
|
|
95
|
+
post_install_message:
|
|
96
|
+
rdoc_options: []
|
|
97
|
+
require_paths:
|
|
98
|
+
- lib
|
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - ">="
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '0'
|
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
105
|
+
requirements:
|
|
106
|
+
- - ">="
|
|
107
|
+
- !ruby/object:Gem::Version
|
|
108
|
+
version: '0'
|
|
109
|
+
requirements: []
|
|
110
|
+
rubyforge_project:
|
|
111
|
+
rubygems_version: 2.5.1
|
|
112
|
+
signing_key:
|
|
113
|
+
specification_version: 4
|
|
114
|
+
summary: A lightweight mime type lookup toy
|
|
115
|
+
test_files: []
|