mimemagic 0.3.5

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of mimemagic might be problematic. Click here for more details.

@@ -0,0 +1,163 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'nokogiri'
4
+
5
+ class String
6
+ alias inspect_old inspect
7
+
8
+ def inspect
9
+ x = b.inspect_old.gsub(/\\x([0-9a-f]{2})/i) do
10
+ '\\%03o' % $1.to_i(16)
11
+ end
12
+ x =~ /[\\']/ ? x : x.gsub('"', '\'')
13
+ end
14
+ end
15
+
16
+ def str2int(s)
17
+ return s.to_i(16) if s[0..1].downcase == '0x'
18
+ return s.to_i(8) if s[0..0].downcase == '0'
19
+ s.to_i(10)
20
+ end
21
+
22
+ def get_matches(parent)
23
+ parent.elements.map {|match|
24
+ if match['mask']
25
+ nil
26
+ else
27
+ type = match['type']
28
+ value = match['value']
29
+ offset = match['offset'].split(':').map {|x| x.to_i }
30
+ offset = offset.size == 2 ? offset[0]..offset[1] : offset[0]
31
+ case type
32
+ when 'string'
33
+ value.gsub!(/\\(x[\dA-Fa-f]{1,2}|0\d{1,3}|\d{1,3}|.)/) { eval("\"\\#{$1}\"") }
34
+ when 'big16'
35
+ value = str2int(value)
36
+ value = ((value >> 8).chr + (value & 0xFF).chr)
37
+ when 'big32'
38
+ value = str2int(value)
39
+ value = (((value >> 24) & 0xFF).chr + ((value >> 16) & 0xFF).chr + ((value >> 8) & 0xFF).chr + (value & 0xFF).chr)
40
+ when 'little16'
41
+ value = str2int(value)
42
+ value = ((value & 0xFF).chr + (value >> 8).chr)
43
+ when 'little32'
44
+ value = str2int(value)
45
+ value = ((value & 0xFF).chr + ((value >> 8) & 0xFF).chr + ((value >> 16) & 0xFF).chr + ((value >> 24) & 0xFF).chr)
46
+ when 'host16' # use little endian
47
+ value = str2int(value)
48
+ value = ((value & 0xFF).chr + (value >> 8).chr)
49
+ when 'host32' # use little endian
50
+ value = str2int(value)
51
+ value = ((value & 0xFF).chr + ((value >> 8) & 0xFF).chr + ((value >> 16) & 0xFF).chr + ((value >> 24) & 0xFF).chr)
52
+ when 'byte'
53
+ value = str2int(value)
54
+ value = value.chr
55
+ end
56
+ children = get_matches(match)
57
+ children.empty? ? [offset, value] : [offset, value, children]
58
+ end
59
+ }.compact
60
+ end
61
+
62
+ if ARGV.size != 1
63
+ puts "Usage: #{$0} <freedesktop.org.xml>"
64
+ exit 1
65
+ end
66
+
67
+ FILE = ARGV[0]
68
+ file = File.new(FILE)
69
+ doc = Nokogiri::XML(file)
70
+ extensions = {}
71
+ types = {}
72
+ magics = []
73
+ (doc/'mime-info/mime-type').each do |mime|
74
+ comments = Hash[*(mime/'comment').map {|comment| [comment['xml:lang'], comment.inner_text] }.flatten]
75
+ type = mime['type']
76
+ subclass = (mime/'sub-class-of').map{|x| x['type']}
77
+ exts = (mime/'glob').map{|x| x['pattern'] =~ /^\*\.([^\[\]]+)$/ ? $1.downcase : nil }.compact
78
+ (mime/'magic').each do |magic|
79
+ priority = magic['priority'].to_i
80
+ matches = get_matches(magic)
81
+ magics << [priority, type, matches]
82
+ end
83
+ if !exts.empty?
84
+ exts.each{|x|
85
+ extensions[x] = type if !extensions.include?(x)
86
+ }
87
+ types[type] = [exts,subclass,comments[nil]]
88
+ end
89
+ end
90
+
91
+ magics = magics.sort {|a,b| [-a[0],a[1]] <=> [-b[0],b[1]] }
92
+
93
+ common_types = [
94
+ "image/jpeg", # .jpg
95
+ "image/png", # .png
96
+ "image/gif", # .gif
97
+ "image/tiff", # .tiff
98
+ "image/bmp", # .bmp
99
+ "image/vnd.adobe.photoshop", # .psd
100
+ "image/webp", # .webp
101
+ "image/svg+xml", # .svg
102
+
103
+ "video/x-msvideo", # .avi
104
+ "video/x-ms-wmv", # .wmv
105
+ "video/mp4", # .mp4, .m4v
106
+ "video/quicktime", # .mov
107
+ "video/mpeg", # .mpeg
108
+ "video/ogg", # .ogv
109
+ "video/webm", # .webm
110
+ "video/x-matroska", # .mkv
111
+ "video/x-flv", # .flv
112
+
113
+ "audio/mpeg", # .mp3
114
+ "audio/x-wav", # .wav
115
+ "audio/aac", # .aac
116
+ "audio/flac", # .flac
117
+ "audio/mp4", # .m4a
118
+ "audio/ogg", # .ogg
119
+
120
+ "application/pdf", # .pdf
121
+ "application/msword", # .doc
122
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document", # .docx
123
+ "application/vnd.ms-powerpoint", # .pps
124
+ "application/vnd.openxmlformats-officedocument.presentationml.slideshow", # .ppsx
125
+ "application/vnd.ms-excel", # .pps
126
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", # .ppsx
127
+ ]
128
+
129
+ common_magics = common_types.map do |common_type|
130
+ magics.find { |_, type, _| type == common_type }
131
+ end
132
+
133
+ magics = (common_magics.compact + magics).uniq
134
+
135
+ puts "# -*- coding: binary -*-"
136
+ puts "# frozen_string_literal: true"
137
+ puts "# Generated from #{FILE}"
138
+ puts "class MimeMagic"
139
+ puts " # @private"
140
+ puts " # :nodoc:"
141
+ puts " EXTENSIONS = {"
142
+ extensions.keys.sort.each do |key|
143
+ puts " '#{key}' => '#{extensions[key]}',"
144
+ end
145
+ puts " }"
146
+ puts " # @private"
147
+ puts " # :nodoc:"
148
+ puts " TYPES = {"
149
+ types.keys.sort.each do |key|
150
+ exts = types[key][0].join(' ')
151
+ parents = types[key][1].sort.join(' ')
152
+ comment = types[key][2].inspect
153
+ puts " '#{key}' => [%w(#{exts}), %w(#{parents}), #{comment}],"
154
+ end
155
+ puts " }"
156
+ puts " # @private"
157
+ puts " # :nodoc:"
158
+ puts " MAGIC = ["
159
+ magics.each do |priority, type, matches|
160
+ puts " ['#{type}', #{matches.inspect}],"
161
+ end
162
+ puts " ]"
163
+ puts "end"
Binary file
Binary file
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/ruby
2
+ print "Hello World"
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,160 @@
1
+ require 'minitest/autorun'
2
+ require 'mimemagic'
3
+ require 'stringio'
4
+ require 'forwardable'
5
+
6
+ class TestMimeMagic < Minitest::Test
7
+ # Do deep copy for constants of initial state.
8
+ INIT_EXTENSIONS = Marshal.load(Marshal.dump(MimeMagic::EXTENSIONS))
9
+ INIT_TYPES = Marshal.load(Marshal.dump(MimeMagic::TYPES))
10
+ INIT_MAGIC = Marshal.load(Marshal.dump(MimeMagic::MAGIC))
11
+
12
+ def setup
13
+ extentions = Marshal.load(Marshal.dump(INIT_EXTENSIONS))
14
+ types = Marshal.load(Marshal.dump(INIT_TYPES))
15
+ magic = Marshal.load(Marshal.dump(INIT_MAGIC))
16
+ MimeMagic.send(:remove_const, :EXTENSIONS) if MimeMagic.const_defined?(:EXTENSIONS)
17
+ MimeMagic.send(:remove_const, :TYPES) if MimeMagic.const_defined?(:TYPES)
18
+ MimeMagic.send(:remove_const, :MAGIC) if MimeMagic.const_defined?(:MAGIC)
19
+ MimeMagic.const_set('EXTENSIONS', extentions)
20
+ MimeMagic.const_set('TYPES', types)
21
+ MimeMagic.const_set('MAGIC', magic)
22
+ end
23
+
24
+ def test_have_type_mediatype_and_subtype
25
+ assert_equal 'text/html', MimeMagic.new('text/html').type
26
+ assert_equal 'text', MimeMagic.new('text/html').mediatype
27
+ assert_equal 'html', MimeMagic.new('text/html').subtype
28
+ end
29
+
30
+ def test_have_mediatype_helpers
31
+ assert MimeMagic.new('text/plain').text?
32
+ assert MimeMagic.new('text/html').text?
33
+ assert MimeMagic.new('application/xhtml+xml').text?
34
+ refute MimeMagic.new('application/octet-stream').text?
35
+ refute MimeMagic.new('image/png').text?
36
+ assert MimeMagic.new('image/png').image?
37
+ assert MimeMagic.new('video/ogg').video?
38
+ assert MimeMagic.new('audio/mpeg').audio?
39
+ end
40
+
41
+ def test_have_hierarchy
42
+ assert MimeMagic.new('text/html').child_of?('text/plain')
43
+ assert MimeMagic.new('text/x-java').child_of?('text/plain')
44
+ end
45
+
46
+ def test_have_extensions
47
+ assert_equal %w(htm html), MimeMagic.new('text/html').extensions
48
+ end
49
+
50
+ def test_have_comment
51
+ assert_equal 'HTML document', MimeMagic.new('text/html').comment
52
+ end
53
+
54
+ def test_recognize_extensions
55
+ assert_equal 'text/html', MimeMagic.by_extension('.html').to_s
56
+ assert_equal 'text/html', MimeMagic.by_extension('html').to_s
57
+ assert_equal 'text/html', MimeMagic.by_extension(:html).to_s
58
+ assert_equal 'application/x-ruby', MimeMagic.by_extension('rb').to_s
59
+ assert_nil MimeMagic.by_extension('crazy')
60
+ assert_nil MimeMagic.by_extension('')
61
+ end
62
+
63
+ def test_recognize_by_a_path
64
+ assert_equal 'text/html', MimeMagic.by_path('/adsjkfa/kajsdfkadsf/kajsdfjasdf.html').to_s
65
+ assert_equal 'text/html', MimeMagic.by_path('something.html').to_s
66
+ assert_equal 'application/x-ruby', MimeMagic.by_path('wtf.rb').to_s
67
+ assert_nil MimeMagic.by_path('where/am.html/crazy')
68
+ assert_nil MimeMagic.by_path('')
69
+ end
70
+
71
+ def test_recognize_xlsx_as_zip_without_magic
72
+ file = "test/files/application.vnd.openxmlformats-officedocument.spreadsheetml.sheet"
73
+ %w(msoffice rubyxl gdocs).each do |variant|
74
+ file = "test/files/application.vnd.openxmlformats-officedocument.spreadsheetml{#{variant}}.sheet"
75
+ assert_equal "application/zip", MimeMagic.by_magic(File.read(file)).to_s
76
+ assert_equal "application/zip", MimeMagic.by_magic(File.open(file, 'rb')).to_s
77
+ end
78
+ end
79
+
80
+ def test_recognize_by_magic
81
+ load "mimemagic/overlay.rb"
82
+ Dir['test/files/*'].each do |file|
83
+ mime = file[11..-1].sub('.', '/').sub(/\{\w+\}/, '')
84
+ assert_equal mime, MimeMagic.by_magic(File.read(file)).to_s
85
+ assert_equal mime, MimeMagic.by_magic(File.open(file, 'rb')).to_s
86
+ end
87
+ end
88
+
89
+ def test_recognize_all_by_magic
90
+ load 'mimemagic/overlay.rb'
91
+ %w(msoffice rubyxl gdocs).each do |variant|
92
+ file = "test/files/application.vnd.openxmlformats-officedocument.spreadsheetml{#{variant}}.sheet"
93
+ mimes = %w[application/vnd.openxmlformats-officedocument.spreadsheetml.sheet application/zip]
94
+ assert_equal mimes, MimeMagic.all_by_magic(File.read(file)).map(&:type)
95
+ end
96
+ end
97
+
98
+ def test_have_add
99
+ MimeMagic.add('application/mimemagic-test',
100
+ extensions: %w(ext1 ext2),
101
+ parents: 'application/xml',
102
+ comment: 'Comment')
103
+ assert_equal 'application/mimemagic-test', MimeMagic.by_extension('ext1').to_s
104
+ assert_equal 'application/mimemagic-test', MimeMagic.by_extension('ext2').to_s
105
+ assert_equal 'Comment', MimeMagic.by_extension('ext2').comment
106
+ assert_equal %w(ext1 ext2), MimeMagic.new('application/mimemagic-test').extensions
107
+ assert MimeMagic.new('application/mimemagic-test').child_of?('text/plain')
108
+ end
109
+
110
+ def test_process_magic
111
+ MimeMagic.add('application/mimemagic-test',
112
+ magic: [[0, 'MAGICTEST'], # MAGICTEST at position 0
113
+ [1, 'MAGICTEST'], # MAGICTEST at position 1
114
+ [9..12, 'MAGICTEST'], # MAGICTEST starting at position 9 to 12
115
+ [2, 'MAGICTEST', [[0, 'X'], [0, 'Y']]]]) # MAGICTEST at position 2 and (X at 0 or Y at 0)
116
+
117
+ assert_equal 'application/mimemagic-test', MimeMagic.by_magic('MAGICTEST').to_s
118
+ assert_equal 'application/mimemagic-test', MimeMagic.by_magic('XMAGICTEST').to_s
119
+ assert_equal 'application/mimemagic-test', MimeMagic.by_magic(' MAGICTEST').to_s
120
+ assert_equal 'application/mimemagic-test', MimeMagic.by_magic('123456789MAGICTEST').to_s
121
+ assert_equal 'application/mimemagic-test', MimeMagic.by_magic('123456789ABMAGICTEST').to_s
122
+ assert_equal 'application/mimemagic-test', MimeMagic.by_magic('123456789ABCMAGICTEST').to_s
123
+ assert_nil MimeMagic.by_magic('123456789ABCDMAGICTEST')
124
+ assert_equal 'application/mimemagic-test', MimeMagic.by_magic('X MAGICTEST').to_s
125
+ assert_equal 'application/mimemagic-test', MimeMagic.by_magic('Y MAGICTEST').to_s
126
+ assert_nil MimeMagic.by_magic('Z MAGICTEST')
127
+
128
+ assert_equal 'application/mimemagic-test', MimeMagic.by_magic(StringIO.new 'MAGICTEST').to_s
129
+ assert_equal 'application/mimemagic-test', MimeMagic.by_magic(StringIO.new 'XMAGICTEST').to_s
130
+ assert_equal 'application/mimemagic-test', MimeMagic.by_magic(StringIO.new ' MAGICTEST').to_s
131
+ assert_equal 'application/mimemagic-test', MimeMagic.by_magic(StringIO.new '123456789MAGICTEST').to_s
132
+ assert_equal 'application/mimemagic-test', MimeMagic.by_magic(StringIO.new '123456789ABMAGICTEST').to_s
133
+ assert_equal 'application/mimemagic-test', MimeMagic.by_magic(StringIO.new '123456789ABCMAGICTEST').to_s
134
+ assert_nil MimeMagic.by_magic(StringIO.new '123456789ABCDMAGICTEST')
135
+ assert_equal 'application/mimemagic-test', MimeMagic.by_magic(StringIO.new 'X MAGICTEST').to_s
136
+ assert_equal 'application/mimemagic-test', MimeMagic.by_magic(StringIO.new 'Y MAGICTEST').to_s
137
+ assert_nil MimeMagic.by_magic(StringIO.new 'Z MAGICTEST')
138
+ end
139
+
140
+ class IOObject
141
+ def initialize
142
+ @io = StringIO.new('MAGICTEST')
143
+ end
144
+
145
+ extend Forwardable
146
+ delegate [:read, :size, :rewind, :eof?, :close] => :@io
147
+ end
148
+
149
+ class StringableObject
150
+ def to_s
151
+ 'MAGICTEST'
152
+ end
153
+ end
154
+
155
+ def test_handle_different_file_objects
156
+ MimeMagic.add('application/mimemagic-test', magic: [[0, 'MAGICTEST']])
157
+ assert_equal 'application/mimemagic-test', MimeMagic.by_magic(IOObject.new).to_s
158
+ assert_equal 'application/mimemagic-test', MimeMagic.by_magic(StringableObject.new).to_s
159
+ end
160
+ end
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mimemagic
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.5
5
+ platform: ruby
6
+ authors:
7
+ - Daniel Mendler
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-05-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: minitest
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '5.11'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '5.11'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Fast mime detection by extension or content in pure ruby (Uses freedesktop.org.xml
42
+ shared-mime-info database)
43
+ email:
44
+ - mail@daniel-mendler.de
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - ".gitignore"
50
+ - ".travis.yml"
51
+ - ".yardopts"
52
+ - CHANGELOG.md
53
+ - Gemfile
54
+ - LICENSE
55
+ - README.md
56
+ - Rakefile
57
+ - lib/mimemagic.rb
58
+ - lib/mimemagic/overlay.rb
59
+ - lib/mimemagic/tables.rb
60
+ - lib/mimemagic/version.rb
61
+ - mimemagic.gemspec
62
+ - script/freedesktop.org.xml
63
+ - script/generate-mime.rb
64
+ - test/files/application.gzip
65
+ - test/files/application.vnd.openxmlformats-officedocument.spreadsheetml{gdocs}.sheet
66
+ - test/files/application.vnd.openxmlformats-officedocument.spreadsheetml{msoffice}.sheet
67
+ - test/files/application.vnd.openxmlformats-officedocument.spreadsheetml{rubyxl}.sheet
68
+ - test/files/application.x-bzip
69
+ - test/files/application.x-ruby
70
+ - test/files/application.x-tar
71
+ - test/files/application.zip
72
+ - test/files/image.jpeg
73
+ - test/files/image.png
74
+ - test/mimemagic_test.rb
75
+ homepage: https://github.com/minad/mimemagic
76
+ licenses:
77
+ - MIT
78
+ metadata:
79
+ changelog_uri: https://github.com/minad/mimemagic/blob/master/CHANGELOG.md
80
+ source_code_uri: https://github.com/minad/mimemagic
81
+ bug_tracker_uri: https://github.com/minad/mimemagic/issues
82
+ post_install_message:
83
+ rdoc_options: []
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ requirements: []
97
+ rubyforge_project:
98
+ rubygems_version: 2.7.6.2
99
+ signing_key:
100
+ specification_version: 4
101
+ summary: Fast mime detection by extension or content
102
+ test_files: []