libmagic_rb 0.1.1.pre.alpha → 0.1.2.pre.gamma
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 +4 -4
- data/README.md +65 -17
- data/ext/libmagic/func.h +197 -17
- data/ext/libmagic/magic.c +78 -8
- data/ext/libmagic/modes.h +69 -4
- data/ext/libmagic/params.h +36 -2
- data/lib/libmagic_rb/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 116d3dc132643a74f2a887128844a9faa5a4b0a53b7aded5e70bd296087ad005
|
|
4
|
+
data.tar.gz: 77f551eddaae7a4d1e70840608ec008cc509569d5c9153d0e07f7d710fc371e7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 804a95966aeca5e305ff5b6d18a733528dcbf179617cefb461bd779c0dbbb8aa044d6edeca9a55b2b04b62c8c6b8c69b82f8d0a4c7663eba43e6798b8ab51a31
|
|
7
|
+
data.tar.gz: fefe9f019f2decd1e85f7836eacbac01bc6c5e9f22beb22d5e271b903eed83d7b6e25d942e3460be4a2f92d9312faa4eaac477775b6c75c36e23d68035634813
|
data/README.md
CHANGED
|
@@ -1,35 +1,79 @@
|
|
|
1
|
-
# LibmagicRb
|
|
1
|
+
# LibmagicRb [](https://rubygems.org/gems/libmagic_rb) 
|
|
2
|
+
|
|
2
3
|
Adds ability to check mime-type of a file using the libmagic ([magic(4)](https://man7.org/linux/man-pages/man4/magic.4.html)).
|
|
3
4
|
It uses native extensions and it's quite performant.
|
|
4
5
|
|
|
5
6
|
## Pre-Installation
|
|
6
|
-
On Linux, you need to install libmagic.
|
|
7
|
+
On Linux, you need to install libmagic. The version we recommend is at least 5.36.
|
|
8
|
+
But if you have an older version of libmagic, it will compile and work flawlessly but with a few caveats:
|
|
9
|
+
|
|
10
|
+
+ Many constants (modes and params) will be not defined
|
|
11
|
+
+ LibmagicRb::MAGIC_VERSION constant will be set to 0.
|
|
12
|
+
+ Few methods will not work.
|
|
13
|
+
some methods that can return a String or Integer will return nil (like setparam and getparam).
|
|
14
|
+
|
|
15
|
+
[ Do note that the minimum tested version is 5.11, older than that may fail to compile the gem ]
|
|
7
16
|
|
|
8
|
-
|
|
17
|
+
You also need Ruby > 1.9.0 in order to run this gem.
|
|
18
|
+
|
|
19
|
+
With that info in mind, let's continue to the installation part for your Linux distributions...
|
|
20
|
+
|
|
21
|
+
#### Arch / Manjaro / Archlabs / Garuda Linux / Hefftor Linux & other Arch Based Linux
|
|
9
22
|
|
|
10
23
|
```
|
|
11
|
-
# pacman -S file gcc make
|
|
24
|
+
# pacman -S ruby file gcc make --needed
|
|
12
25
|
```
|
|
13
26
|
|
|
14
|
-
#### Debian / Ubuntu / Linux Mint /
|
|
27
|
+
#### Debian / Ubuntu / Linux Mint / Deepin / Pop!_OS / RaspberryPi OS & other Debian Based Linux
|
|
15
28
|
|
|
16
29
|
```
|
|
17
|
-
# apt install libmagic-dev ruby-dev gcc make
|
|
30
|
+
# apt install ruby libmagic-dev ruby-dev gcc make
|
|
18
31
|
```
|
|
19
32
|
|
|
20
|
-
#### Fedora
|
|
33
|
+
#### Fedora / Amazon Linux / CentOS & Other RedHat Based Linux
|
|
21
34
|
|
|
22
35
|
```
|
|
23
|
-
# yum install file-devel ruby-devel gcc make
|
|
36
|
+
# yum install ruby file-devel ruby-devel gcc make
|
|
24
37
|
```
|
|
25
38
|
|
|
26
39
|
#### OpenSUSE
|
|
27
40
|
|
|
28
41
|
```
|
|
29
|
-
zypper in ruby ruby-devel file-devel gcc make
|
|
42
|
+
# zypper in ruby ruby-devel file-devel gcc make
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
#### Gentoo
|
|
46
|
+
|
|
47
|
+
There are already make, and magic.h available for Gentoo. You just need Ruby:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
# emerge --ask dev-lang/ruby
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
#### DragonflyBSD / FreeBSD
|
|
54
|
+
|
|
55
|
+
Versions upto 0.1.2 is tested on DragonflyBSD (Version 6.0-SYNTH).
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
# pkg install ruby devel/ruby-gems gcc gmake
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
#### MacOS
|
|
62
|
+
|
|
63
|
+
You can install libmagic with homebrew:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
$ brew install libmagic
|
|
67
|
+
|
|
68
|
+
# if the link is already created is going to fail, don't worry about that
|
|
69
|
+
$ brew link libmagic
|
|
30
70
|
```
|
|
31
71
|
|
|
32
|
-
|
|
72
|
+
[ Source: [ eparreno/gist:1845561 ](https://gist.github.com/eparreno/1845561) ]
|
|
73
|
+
|
|
74
|
+
#### Windows
|
|
75
|
+
|
|
76
|
+
Windows is currently not tested, hence the support is unknown.
|
|
33
77
|
|
|
34
78
|
## Installation
|
|
35
79
|
|
|
@@ -51,6 +95,9 @@ Or install it yourself as:
|
|
|
51
95
|
$ gem install libmagic_rb
|
|
52
96
|
```
|
|
53
97
|
|
|
98
|
+
We recommend getting the gem only from Rubygems.org. Do not download this repo as zip, compile to install the gem.
|
|
99
|
+
A rubygem version is released after various tests. Any branch here including Master branch can be unstable can even segfault your app. You've been warned!
|
|
100
|
+
|
|
54
101
|
## Usage
|
|
55
102
|
The target of this gem is to add mime-type checking easily.
|
|
56
103
|
|
|
@@ -162,18 +209,19 @@ cookie.setparam(LibmagicRb::MAGIC_PARAM_REGEX_MAX, 2 ** 14) # => 16384; but can
|
|
|
162
209
|
|
|
163
210
|
#### Notes:
|
|
164
211
|
|
|
165
|
-
+ To get the parameters, you can refer to the [man page](https://man7.org/linux/man-pages/man3/magic_getflags.3.html).
|
|
166
|
-
+
|
|
212
|
+
+ To get the parameters, you can run `LibmagicRb.lsparams()` for description, please refer to the [man page](https://man7.org/linux/man-pages/man3/magic_getflags.3.html).
|
|
213
|
+
+ `cookie.setparam()` returns the value after getting the param as well. So you don't need to confirm by calling getparam() again.
|
|
167
214
|
+ The maximum size depends on the parameter. But the value that can be passed should not be more than 2 ** 32.
|
|
215
|
+
+ On older versions of libmagic, where the function isn't available, both getparam() and setparam() will perform no operations, and return nil!
|
|
168
216
|
|
|
169
217
|
## Errors
|
|
170
218
|
The following errors are implemented and raised on appropriate situation:
|
|
171
219
|
|
|
172
|
-
1. LibmagicRb::FileNotFound
|
|
173
|
-
2. LibmagicRb::FileUnreadable
|
|
174
|
-
3. LibmagicRb::InvalidDBError
|
|
175
|
-
4. LibmagicRb::IsDirError
|
|
176
|
-
5. LibmagicRb::FileClosedError
|
|
220
|
+
1. `LibmagicRb::FileNotFound`: When the file is not found.
|
|
221
|
+
2. `LibmagicRb::FileUnreadable`: When the file is unreadable.
|
|
222
|
+
3. `LibmagicRb::InvalidDBError`: When the database given is invalid.
|
|
223
|
+
4. `LibmagicRb::IsDirError`: When the database path is a directory.
|
|
224
|
+
5. `LibmagicRb::FileClosedError`: When the file is already closed (closed?()) but you are trying to access the cookie.
|
|
177
225
|
|
|
178
226
|
## Development
|
|
179
227
|
|
data/ext/libmagic/func.h
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Closes a magic cookie. For example:
|
|
3
|
+
|
|
4
|
+
> cookie = LibmagicRb.new(file: '/usr/share/dict/words')
|
|
5
|
+
# => #<LibmagicRb:0x00005581019fa7e0 @closed=false, @db=nil, @file="/usr/share/dict/words", @mode=1106>
|
|
6
|
+
|
|
7
|
+
> cookie.close
|
|
8
|
+
# => #<LibmagicRb:0x00005581019fa7e0 @closed=true, @db=nil, @file="/usr/share/dict/words", @mode=1106>
|
|
9
|
+
|
|
10
|
+
Returns self.
|
|
11
|
+
*/
|
|
12
|
+
|
|
1
13
|
VALUE _closeGlobal_(volatile VALUE self) {
|
|
2
14
|
RB_UNWRAP(cookie) ;
|
|
3
15
|
|
|
@@ -7,6 +19,23 @@ VALUE _closeGlobal_(volatile VALUE self) {
|
|
|
7
19
|
return self ;
|
|
8
20
|
}
|
|
9
21
|
|
|
22
|
+
/*
|
|
23
|
+
Changes the database path. For example:
|
|
24
|
+
> cookie = LibmagicRb.new(file: '/usr/share/dict/words')
|
|
25
|
+
# => #<LibmagicRb:0x00005581019181b0 @closed=false, @db=nil, @file="/usr/share/dict/words", @mode=1106>
|
|
26
|
+
|
|
27
|
+
> cookie.db = '/usr/share/file/misc/magic.mgc'
|
|
28
|
+
# => "/usr/share/file/misc/magic.mgc"
|
|
29
|
+
|
|
30
|
+
> cookie.check
|
|
31
|
+
# => "text/plain; charset=utf-8"
|
|
32
|
+
|
|
33
|
+
> cookie.close
|
|
34
|
+
# => #<LibmagicRb:0x00005581019181b0 @closed=true, @db="/usr/share/file/misc/magic.mgc", @file="/usr/share/dict/words", @mode=1106>
|
|
35
|
+
|
|
36
|
+
Returns self.
|
|
37
|
+
*/
|
|
38
|
+
|
|
10
39
|
VALUE _loadGlobal_(volatile VALUE self, volatile VALUE dbPath) {
|
|
11
40
|
char *databasePath = NULL ;
|
|
12
41
|
|
|
@@ -27,6 +56,20 @@ VALUE _loadGlobal_(volatile VALUE self, volatile VALUE dbPath) {
|
|
|
27
56
|
return self ;
|
|
28
57
|
}
|
|
29
58
|
|
|
59
|
+
/*
|
|
60
|
+
Check a file with the magic database. For example:
|
|
61
|
+
> cookie = LibmagicRb.new(file: '/usr/share/dict/words')
|
|
62
|
+
# => #<LibmagicRb:0x00005581019181b0 @closed=false, @db=nil, @file="/usr/share/dict/words", @mode=1106>
|
|
63
|
+
|
|
64
|
+
> cookie.check
|
|
65
|
+
# => "text/plain; charset=utf-8"
|
|
66
|
+
|
|
67
|
+
> cookie.close
|
|
68
|
+
# => #<LibmagicRb:0x00005581019181b0 @closed=true, @db="/usr/share/file/misc/magic.mgc", @file="/usr/share/dict/words", @mode=1106>
|
|
69
|
+
|
|
70
|
+
Returns String or nil.
|
|
71
|
+
*/
|
|
72
|
+
|
|
30
73
|
VALUE _checkGlobal_(volatile VALUE self) {
|
|
31
74
|
RB_UNWRAP(cookie) ;
|
|
32
75
|
|
|
@@ -51,51 +94,188 @@ VALUE _checkGlobal_(volatile VALUE self) {
|
|
|
51
94
|
return mt ? rb_str_new_cstr(mt) : Qnil ;
|
|
52
95
|
}
|
|
53
96
|
|
|
97
|
+
/*
|
|
98
|
+
Get parameters for a cookie. For example:
|
|
99
|
+
cookie = LibmagicRb.new(file: '/usr/share/dict/words')
|
|
100
|
+
# => #<LibmagicRb:0x00005581018f35e0 @closed=false, @db=nil, @file="/usr/share/dict/words", @mode=1106>
|
|
101
|
+
|
|
102
|
+
> cookie.getparam(LibmagicRb::MAGIC_PARAM_NAME_MAX)
|
|
103
|
+
# => 50
|
|
104
|
+
|
|
105
|
+
> cookie.close
|
|
106
|
+
# => #<LibmagicRb:0x00005581018f35e0 @closed=true, @db=nil, @file="/usr/share/dict/words", @mode=1106>
|
|
107
|
+
*/
|
|
108
|
+
|
|
54
109
|
VALUE _getParamGlobal_(volatile VALUE self, volatile VALUE param) {
|
|
55
|
-
|
|
110
|
+
#if MAGIC_VERSION > 525
|
|
111
|
+
RB_UNWRAP(cookie) ;
|
|
56
112
|
|
|
57
|
-
|
|
58
|
-
|
|
113
|
+
unsigned int _param = NUM2UINT(param) ;
|
|
114
|
+
unsigned long value ;
|
|
59
115
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
116
|
+
int status = magic_getparam(*cookie, _param, &value) ;
|
|
117
|
+
if (status) return Qnil ;
|
|
118
|
+
return ULONG2NUM(value) ;
|
|
119
|
+
#else
|
|
120
|
+
return Qnil ;
|
|
121
|
+
#endif
|
|
63
122
|
}
|
|
64
123
|
|
|
124
|
+
/*
|
|
125
|
+
Sets parameter for a cookie. For example:
|
|
126
|
+
|
|
127
|
+
> cookie = LibmagicRb.new(file: '/usr/share/dict/words')
|
|
128
|
+
# => #<LibmagicRb:0x00005581019f9840 @closed=false, @db=nil, @file="/usr/share/dict/words", @mode=1106>
|
|
129
|
+
|
|
130
|
+
> cookie.getparam(LibmagicRb::MAGIC_PARAM_NAME_MAX)
|
|
131
|
+
=> 50
|
|
132
|
+
|
|
133
|
+
> cookie.setparam(LibmagicRb::MAGIC_PARAM_NAME_MAX, 101)
|
|
134
|
+
# => 101
|
|
135
|
+
|
|
136
|
+
> cookie.getparam(LibmagicRb::MAGIC_PARAM_NAME_MAX)
|
|
137
|
+
# => 101
|
|
138
|
+
|
|
139
|
+
> cookie.close
|
|
140
|
+
# => #<LibmagicRb:0x00005581019f9840 @closed=true, @db=nil, @file="/usr/share/dict/words", @mode=1106>
|
|
141
|
+
|
|
142
|
+
Returns Integer or nil on failure.
|
|
143
|
+
*/
|
|
144
|
+
|
|
65
145
|
VALUE _setParamGlobal_(volatile VALUE self, volatile VALUE param, volatile VALUE paramVal) {
|
|
66
|
-
|
|
67
|
-
|
|
146
|
+
#if MAGIC_VERSION > 525
|
|
147
|
+
unsigned int _param = NUM2UINT(param) ;
|
|
148
|
+
unsigned long _paramVal = NUM2ULONG(paramVal) ;
|
|
68
149
|
|
|
69
|
-
|
|
150
|
+
RB_UNWRAP(cookie) ;
|
|
70
151
|
|
|
71
|
-
|
|
72
|
-
|
|
152
|
+
unsigned long value ;
|
|
153
|
+
magic_setparam(*cookie, _param, &_paramVal) ;
|
|
73
154
|
|
|
74
|
-
|
|
155
|
+
int status = magic_getparam(*cookie, _param, &value) ;
|
|
156
|
+
if (status) return Qnil ;
|
|
75
157
|
|
|
76
|
-
|
|
77
|
-
|
|
158
|
+
return ULONG2NUM((int)value) ;
|
|
159
|
+
#else
|
|
160
|
+
return Qnil ;
|
|
161
|
+
#endif
|
|
78
162
|
}
|
|
79
163
|
|
|
164
|
+
/*
|
|
165
|
+
Returns a textual description of the contents of the buffer argument with length bytes size.
|
|
166
|
+
|
|
167
|
+
For example:
|
|
168
|
+
|
|
169
|
+
> cookie = LibmagicRb.new(file: '.')
|
|
170
|
+
# => #<LibmagicRb:0x00005582de0d1bf8 @closed=false, @db=nil, @file=".", @mode=1106>
|
|
171
|
+
|
|
172
|
+
> cookie.magic_buffer("%PDF-1.3\r\n")
|
|
173
|
+
# => "application/pdf; charset=us-ascii"
|
|
174
|
+
|
|
175
|
+
> cookie.close
|
|
176
|
+
# => #<LibmagicRb:0x00005582de0d1bf8 @closed=true, @db=nil, @file=".", @mode=1106>
|
|
177
|
+
|
|
178
|
+
Note that it automatically loads the database.
|
|
179
|
+
|
|
180
|
+
Returns either String or nil.
|
|
181
|
+
*/
|
|
182
|
+
|
|
80
183
|
VALUE _bufferGlobal_(volatile VALUE self, volatile VALUE string) {
|
|
81
184
|
RB_UNWRAP(cookie) ;
|
|
82
185
|
|
|
186
|
+
VALUE db = rb_iv_get(self, "@db") ;
|
|
187
|
+
|
|
188
|
+
char *database = NULL ;
|
|
189
|
+
if(RB_TYPE_P(db, T_STRING)) {
|
|
190
|
+
database = StringValuePtr(db) ;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if(database) magic_validate_db(*cookie, database) ;
|
|
194
|
+
magic_load(*cookie, database) ;
|
|
195
|
+
|
|
83
196
|
char *buffer = StringValuePtr(string) ;
|
|
84
|
-
const char *buf = magic_buffer(*cookie, buffer,
|
|
197
|
+
const char *buf = magic_buffer(*cookie, buffer, strlen(buffer)) ;
|
|
85
198
|
|
|
86
|
-
return rb_str_new_cstr(buf) ;
|
|
199
|
+
return buf ? rb_str_new_cstr(buf) : Qnil ;
|
|
87
200
|
}
|
|
88
201
|
|
|
202
|
+
/*
|
|
203
|
+
Dumps all magic entries in a human
|
|
204
|
+
readable format, dumping first the entries that are matched against
|
|
205
|
+
binary files and then the ones that match text files.
|
|
206
|
+
|
|
207
|
+
For example:
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
> cookie = LibmagicRb.new(file: '.')
|
|
211
|
+
# => #<LibmagicRb:0x000055cf280a9b30 @closed=false, @db=nil, @file=".", @mode=1106>
|
|
212
|
+
|
|
213
|
+
> cookie.magic_list
|
|
214
|
+
Set 0:
|
|
215
|
+
Binary patterns:
|
|
216
|
+
Strength = 500@47: Biosig/Brainvision Marker file [biosig/brainvision]
|
|
217
|
+
Strength = 490@122: Biosig/TMSiLOG [biosig/tmsilog]
|
|
218
|
+
Strength = 461@127: Biosig/SYNERGY [biosig/synergy]
|
|
219
|
+
Strength = 460@46: Biosig/Brainvision V-Amp file []
|
|
220
|
+
Strength = 410@45: Biosig/Brainvision data file []
|
|
221
|
+
Strength = 380@6: OpenSSH private key []
|
|
222
|
+
Strength = 370@1266: Novell message librarian data []
|
|
223
|
+
.
|
|
224
|
+
.
|
|
225
|
+
.
|
|
226
|
+
# => 0
|
|
227
|
+
|
|
228
|
+
> cookie.close
|
|
229
|
+
=> #<LibmagicRb:0x000055cf280a9b30 @closed=true, @db=nil, @file=".", @mode=1106>
|
|
230
|
+
*/
|
|
231
|
+
|
|
89
232
|
VALUE _listGlobal_(volatile VALUE self) {
|
|
90
233
|
RB_UNWRAP(cookie) ;
|
|
91
234
|
|
|
92
235
|
VALUE db = rb_iv_get(self, "@db") ;
|
|
93
|
-
char *database = StringValuePtr(db) ;
|
|
94
236
|
|
|
237
|
+
char *database = NULL ;
|
|
238
|
+
if (RB_TYPE_P(db, T_STRING)) {
|
|
239
|
+
database = StringValuePtr(db) ;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if(database) magic_validate_db(*cookie, database) ;
|
|
95
243
|
int status = magic_list(*cookie, database) ;
|
|
244
|
+
|
|
96
245
|
return INT2FIX(status) ;
|
|
97
246
|
}
|
|
98
247
|
|
|
248
|
+
/*
|
|
249
|
+
Set flags/modes for a cookie (not to be confused with params).
|
|
250
|
+
It's same setting mode through the setter cookie.mode = mode.
|
|
251
|
+
|
|
252
|
+
For example:
|
|
253
|
+
|
|
254
|
+
> cookie = LibmagicRb.new(file: '.')
|
|
255
|
+
# => #<LibmagicRb:0x00005583732e1070 @closed=false, @db=nil, @file=".", @mode=1106>
|
|
256
|
+
|
|
257
|
+
> cookie.check
|
|
258
|
+
# => "inode/directory; charset=binary"
|
|
259
|
+
|
|
260
|
+
> cookie.setflags(LibmagicRb::MAGIC_RAW)
|
|
261
|
+
# => 256
|
|
262
|
+
|
|
263
|
+
> cookie.check
|
|
264
|
+
# => "directory"
|
|
265
|
+
|
|
266
|
+
#### Similarly you can also do this ####
|
|
267
|
+
|
|
268
|
+
> cookie.mode = LibmagicRb::MAGIC_MIME
|
|
269
|
+
# => 1040
|
|
270
|
+
|
|
271
|
+
> cookie.check
|
|
272
|
+
# => "inode/directory; charset=binary"
|
|
273
|
+
|
|
274
|
+
#### Close the cookie when done ####
|
|
275
|
+
> cookie.close
|
|
276
|
+
# => #<LibmagicRb:0x00005583732e1070 @closed=true, @db=nil, @file=".", @mode=256>
|
|
277
|
+
*/
|
|
278
|
+
|
|
99
279
|
VALUE _setflagsGlobal_(volatile VALUE self, volatile VALUE flags) {
|
|
100
280
|
unsigned int flag = NUM2UINT(flags) ;
|
|
101
281
|
|
data/ext/libmagic/magic.c
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#include <magic.h>
|
|
2
2
|
#include <stdio.h>
|
|
3
3
|
#include <unistd.h>
|
|
4
|
+
#include <sys/stat.h>
|
|
4
5
|
#include "ruby.h"
|
|
5
6
|
|
|
6
7
|
/*
|
|
@@ -10,6 +11,10 @@
|
|
|
10
11
|
#include "params.h"
|
|
11
12
|
#include "definitions.h"
|
|
12
13
|
|
|
14
|
+
#ifndef MAGIC_VERSION
|
|
15
|
+
#define MAGIC_VERSION 0
|
|
16
|
+
#endif
|
|
17
|
+
|
|
13
18
|
/*
|
|
14
19
|
* Errors
|
|
15
20
|
*/
|
|
@@ -39,13 +44,30 @@ static rb_data_type_t fileType = {
|
|
|
39
44
|
},
|
|
40
45
|
|
|
41
46
|
.data = NULL,
|
|
42
|
-
|
|
47
|
+
|
|
48
|
+
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
|
|
49
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
50
|
+
#endif
|
|
43
51
|
} ;
|
|
44
52
|
|
|
45
53
|
#include "validations.h"
|
|
46
54
|
#include "func.h"
|
|
47
55
|
|
|
48
|
-
|
|
56
|
+
/*
|
|
57
|
+
Directly check a file with LibmagicRb, without creating any sort of cookies:
|
|
58
|
+
|
|
59
|
+
LibmagicRb.check(file: '/tmp/', db: '/usr/share/file/misc/magic.mgc', mode: LibmagicRb::MAGIC_CHECK) # => "sticky, directory"
|
|
60
|
+
|
|
61
|
+
[file] The key `file:` is the filename to check. Should be a string
|
|
62
|
+
|
|
63
|
+
[db] The key `db:` can be left as nil. Or you can give it the path of the current magic database.
|
|
64
|
+
|
|
65
|
+
[mode] The key `mode` can be any of the LibmagicRb.lsmodes().
|
|
66
|
+
To combine modes you can use `|`. For example:
|
|
67
|
+
`mode: LibmagicRb::MAGIC_CHECK | LibmagicRb::MAGIC_SYMLINK | Libmagic_MAGIC_MIME`
|
|
68
|
+
If `mode` key is nil, it will default to `MAGIC_MIME | MAGIC_CHECK | MAGIC_SYMLINK`
|
|
69
|
+
*/
|
|
70
|
+
static VALUE _check_(volatile VALUE obj, volatile VALUE args) {
|
|
49
71
|
if(!RB_TYPE_P(args, T_HASH)) {
|
|
50
72
|
rb_raise(rb_eArgError, "Expected hash as argument.") ;
|
|
51
73
|
}
|
|
@@ -103,6 +125,43 @@ VALUE _check_(volatile VALUE obj, volatile VALUE args) {
|
|
|
103
125
|
return retVal ;
|
|
104
126
|
}
|
|
105
127
|
|
|
128
|
+
/*
|
|
129
|
+
Intializes a magic cookie that can be used multiple times.
|
|
130
|
+
The benefit of this is to assgign various cookies and change flags of each cookie.
|
|
131
|
+
|
|
132
|
+
For example:
|
|
133
|
+
|
|
134
|
+
> cookie = LibmagicRb.new(file: '/tmp')
|
|
135
|
+
# => #<LibmagicRb:0x000055810139f738 @closed=false, @db=nil, @file="/tmp", @mode=1106>
|
|
136
|
+
|
|
137
|
+
> cookie.check
|
|
138
|
+
# => "inode/directory; charset=binary"
|
|
139
|
+
|
|
140
|
+
> cookie.setflags(LibmagicRb::MAGIC_RAW)
|
|
141
|
+
# => 256
|
|
142
|
+
|
|
143
|
+
> cookie.check
|
|
144
|
+
# => "sticky, directory"
|
|
145
|
+
|
|
146
|
+
> cookie2 = LibmagicRb.new(file: '/usr/share/dict/words')
|
|
147
|
+
# => #<LibmagicRb:0x000055810190a060 @closed=false, @db=nil, @file="/usr/share/dict/words", @mode=1106>
|
|
148
|
+
|
|
149
|
+
> cookie2.check
|
|
150
|
+
# => "text/plain; charset=utf-8"
|
|
151
|
+
|
|
152
|
+
> cookie.close
|
|
153
|
+
# => #<LibmagicRb:0x000055810139f738 @closed=true, @db=nil, @file="/tmp", @mode=256>
|
|
154
|
+
|
|
155
|
+
> cookie.closed?
|
|
156
|
+
# => true
|
|
157
|
+
|
|
158
|
+
> cookie2.closed?
|
|
159
|
+
# => false
|
|
160
|
+
|
|
161
|
+
Here in this example, we can't use cookie, but cookie2 is a different magic_t wrapper, so we can continue using that.
|
|
162
|
+
Flags/modes applied to cookie, will not affect cookie2 as well. Think of them as totally different containers.
|
|
163
|
+
Of course, you must close cookies when you don't need them. Otherwise it can use memories unless GC is triggered.
|
|
164
|
+
*/
|
|
106
165
|
VALUE rb_libmagicRb_initialize(volatile VALUE self, volatile VALUE args) {
|
|
107
166
|
// Database Path
|
|
108
167
|
if(!RB_TYPE_P(args, T_HASH)) {
|
|
@@ -111,14 +170,11 @@ VALUE rb_libmagicRb_initialize(volatile VALUE self, volatile VALUE args) {
|
|
|
111
170
|
|
|
112
171
|
VALUE argDBPath = rb_hash_aref(args, ID2SYM(rb_intern("db"))) ;
|
|
113
172
|
|
|
114
|
-
char *databasePath ;
|
|
115
173
|
if (RB_TYPE_P(argDBPath, T_NIL)) {
|
|
116
|
-
databasePath = NULL ;
|
|
117
174
|
rb_ivar_set(self, rb_intern("@db"), Qnil) ;
|
|
118
175
|
} else if (!RB_TYPE_P(argDBPath, T_STRING)) {
|
|
119
176
|
rb_raise(rb_eArgError, "Database name must be an instance of String.") ;
|
|
120
177
|
} else {
|
|
121
|
-
databasePath = StringValuePtr(argDBPath) ;
|
|
122
178
|
rb_ivar_set(self, rb_intern("@db"), argDBPath) ;
|
|
123
179
|
}
|
|
124
180
|
|
|
@@ -169,6 +225,10 @@ void Init_main() {
|
|
|
169
225
|
/*
|
|
170
226
|
* Libmagic Errors
|
|
171
227
|
*/
|
|
228
|
+
|
|
229
|
+
/*
|
|
230
|
+
Adds ability to check mime-type of a file using the libmagic (magic(4)). It uses native extensions and it's quite performant.
|
|
231
|
+
*/
|
|
172
232
|
VALUE cLibmagicRb = rb_define_class("LibmagicRb", rb_cObject) ;
|
|
173
233
|
|
|
174
234
|
rb_eFileNotFoundError = rb_define_class_under(cLibmagicRb, "FileNotFound", rb_eRuntimeError) ;
|
|
@@ -183,9 +243,19 @@ void Init_main() {
|
|
|
183
243
|
modes(cLibmagicRb) ;
|
|
184
244
|
params(cLibmagicRb) ;
|
|
185
245
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
246
|
+
|
|
247
|
+
#if MAGIC_VERSION > 525
|
|
248
|
+
char version[6] ;
|
|
249
|
+
sprintf(version, "%0.2f", magic_version() / 100.0) ;
|
|
250
|
+
|
|
251
|
+
/*
|
|
252
|
+
LibmagicRb::MAGIC_VERSION returns the magic version of the library.
|
|
253
|
+
For older libmagic version, this can be undefined, so this method will return "0" instead.
|
|
254
|
+
*/
|
|
255
|
+
rb_define_const(cLibmagicRb, "MAGIC_VERSION", rb_str_new_cstr(version)) ;
|
|
256
|
+
#else
|
|
257
|
+
rb_define_const(cLibmagicRb, "MAGIC_VERSION", rb_str_new_cstr("0")) ;
|
|
258
|
+
#endif
|
|
189
259
|
|
|
190
260
|
/*
|
|
191
261
|
* Singleton Methods
|
data/ext/libmagic/modes.h
CHANGED
|
@@ -15,24 +15,57 @@ void modes(volatile VALUE rb_klass) {
|
|
|
15
15
|
rb_define_const(rb_klass, "MAGIC_RAW", INT2FIX(MAGIC_RAW)) ;
|
|
16
16
|
rb_define_const(rb_klass, "MAGIC_ERROR", INT2FIX(MAGIC_ERROR)) ;
|
|
17
17
|
rb_define_const(rb_klass, "MAGIC_APPLE", INT2FIX(MAGIC_APPLE)) ;
|
|
18
|
+
|
|
19
|
+
#ifdef MAGIC_EXTENSION
|
|
18
20
|
rb_define_const(rb_klass, "MAGIC_EXTENSION", INT2FIX(MAGIC_EXTENSION)) ;
|
|
21
|
+
#endif
|
|
22
|
+
|
|
23
|
+
#ifdef MAGIC_COMPRESS_TRANSP
|
|
19
24
|
rb_define_const(rb_klass, "MAGIC_COMPRESS_TRANSP", INT2FIX(MAGIC_COMPRESS_TRANSP)) ;
|
|
25
|
+
#endif
|
|
26
|
+
|
|
27
|
+
#ifdef MAGIC_NO_CHECK_APPTYPE
|
|
20
28
|
rb_define_const(rb_klass, "MAGIC_NO_CHECK_APPTYPE", INT2FIX(MAGIC_NO_CHECK_APPTYPE)) ;
|
|
29
|
+
#endif
|
|
30
|
+
|
|
31
|
+
#ifdef MAGIC_NO_CHECK_CDF
|
|
21
32
|
rb_define_const(rb_klass, "MAGIC_NO_CHECK_CDF", INT2FIX(MAGIC_NO_CHECK_CDF)) ;
|
|
33
|
+
#endif
|
|
34
|
+
|
|
35
|
+
#ifdef MAGIC_NO_CHECK_COMPRESS
|
|
22
36
|
rb_define_const(rb_klass, "MAGIC_NO_CHECK_COMPRESS", INT2FIX(MAGIC_NO_CHECK_COMPRESS)) ;
|
|
37
|
+
#endif
|
|
38
|
+
|
|
39
|
+
#ifdef MAGIC_NO_CHECK_ELF
|
|
23
40
|
rb_define_const(rb_klass, "MAGIC_NO_CHECK_ELF", INT2FIX(MAGIC_NO_CHECK_ELF)) ;
|
|
41
|
+
#endif
|
|
42
|
+
|
|
43
|
+
#ifdef MAGIC_NO_CHECK_ENCODING
|
|
24
44
|
rb_define_const(rb_klass, "MAGIC_NO_CHECK_ENCODING", INT2FIX(MAGIC_NO_CHECK_ENCODING)) ;
|
|
45
|
+
#endif
|
|
46
|
+
|
|
47
|
+
#ifdef MAGIC_NO_CHECK_SOFT
|
|
25
48
|
rb_define_const(rb_klass, "MAGIC_NO_CHECK_SOFT", INT2FIX(MAGIC_NO_CHECK_SOFT)) ;
|
|
49
|
+
#endif
|
|
50
|
+
|
|
51
|
+
#ifdef MAGIC_NO_CHECK_TAR
|
|
26
52
|
rb_define_const(rb_klass, "MAGIC_NO_CHECK_TAR", INT2FIX(MAGIC_NO_CHECK_TAR)) ;
|
|
53
|
+
#endif
|
|
54
|
+
|
|
55
|
+
#ifdef MAGIC_NO_CHECK_TEXT
|
|
27
56
|
rb_define_const(rb_klass, "MAGIC_NO_CHECK_TEXT", INT2FIX(MAGIC_NO_CHECK_TEXT)) ;
|
|
57
|
+
#endif
|
|
58
|
+
|
|
59
|
+
#ifdef MAGIC_NO_CHECK_TOKENS
|
|
28
60
|
rb_define_const(rb_klass, "MAGIC_NO_CHECK_TOKENS", INT2FIX(MAGIC_NO_CHECK_TOKENS)) ;
|
|
61
|
+
#endif
|
|
29
62
|
|
|
30
63
|
#ifdef MAGIC_NO_CHECK_JSON
|
|
31
|
-
|
|
64
|
+
rb_define_const(rb_klass, "MAGIC_NO_CHECK_JSON", INT2FIX(MAGIC_NO_CHECK_JSON)) ;
|
|
32
65
|
#endif
|
|
33
66
|
|
|
34
67
|
#ifdef MAGIC_NO_CHECK_CSV
|
|
35
|
-
|
|
68
|
+
rb_define_const(rb_klass, "MAGIC_NO_CHECK_CSV", INT2FIX(MAGIC_NO_CHECK_CSV)) ;
|
|
36
69
|
#endif
|
|
37
70
|
}
|
|
38
71
|
|
|
@@ -53,24 +86,56 @@ VALUE lsmodes(volatile VALUE obj) {
|
|
|
53
86
|
rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_RAW")), INT2FIX(MAGIC_RAW)) ;
|
|
54
87
|
rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_ERROR")), INT2FIX(MAGIC_ERROR)) ;
|
|
55
88
|
rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_APPLE")), INT2FIX(MAGIC_APPLE)) ;
|
|
89
|
+
#ifdef MAGIC_EXTENSION
|
|
56
90
|
rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_EXTENSION")), INT2FIX(MAGIC_EXTENSION)) ;
|
|
91
|
+
#endif
|
|
92
|
+
|
|
93
|
+
#ifdef MAGIC_COMPRESS_TRANSP
|
|
57
94
|
rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_COMPRESS_TRANSP")), INT2FIX(MAGIC_COMPRESS_TRANSP)) ;
|
|
95
|
+
#endif
|
|
96
|
+
|
|
97
|
+
#ifdef MAGIC_NO_CHECK_APPTYPE
|
|
58
98
|
rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_NO_CHECK_APPTYPE")), INT2FIX(MAGIC_NO_CHECK_APPTYPE)) ;
|
|
99
|
+
#endif
|
|
100
|
+
|
|
101
|
+
#ifdef MAGIC_NO_CHECK_CDF
|
|
59
102
|
rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_NO_CHECK_CDF")), INT2FIX(MAGIC_NO_CHECK_CDF)) ;
|
|
103
|
+
#endif
|
|
104
|
+
|
|
105
|
+
#ifdef MAGIC_NO_CHECK_COMPRESS
|
|
60
106
|
rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_NO_CHECK_COMPRESS")), INT2FIX(MAGIC_NO_CHECK_COMPRESS)) ;
|
|
107
|
+
#endif
|
|
108
|
+
|
|
109
|
+
#ifdef MAGIC_NO_CHECK_ELF
|
|
61
110
|
rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_NO_CHECK_ELF")), INT2FIX(MAGIC_NO_CHECK_ELF)) ;
|
|
111
|
+
#endif
|
|
112
|
+
|
|
113
|
+
#ifdef MAGIC_NO_CHECK_ENCODING
|
|
62
114
|
rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_NO_CHECK_ENCODING")), INT2FIX(MAGIC_NO_CHECK_ENCODING)) ;
|
|
115
|
+
#endif
|
|
116
|
+
|
|
117
|
+
#ifdef MAGIC_NO_CHECK_SOFT
|
|
63
118
|
rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_NO_CHECK_SOFT")), INT2FIX(MAGIC_NO_CHECK_SOFT)) ;
|
|
119
|
+
#endif
|
|
120
|
+
|
|
121
|
+
#ifdef MAGIC_NO_CHECK_TAR
|
|
64
122
|
rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_NO_CHECK_TAR")), INT2FIX(MAGIC_NO_CHECK_TAR)) ;
|
|
123
|
+
#endif
|
|
124
|
+
|
|
125
|
+
#ifdef MAGIC_NO_CHECK_TEXT
|
|
65
126
|
rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_NO_CHECK_TEXT")), INT2FIX(MAGIC_NO_CHECK_TEXT)) ;
|
|
127
|
+
#endif
|
|
128
|
+
|
|
129
|
+
#ifdef MAGIC_NO_CHECK_TOKENS
|
|
66
130
|
rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_NO_CHECK_TOKENS")), INT2FIX(MAGIC_NO_CHECK_TOKENS)) ;
|
|
131
|
+
#endif
|
|
67
132
|
|
|
68
133
|
#ifdef MAGIC_NO_CHECK_CSV
|
|
69
|
-
|
|
134
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_NO_CHECK_CSV")), INT2FIX(MAGIC_NO_CHECK_CSV)) ;
|
|
70
135
|
#endif
|
|
71
136
|
|
|
72
137
|
#ifdef MAGIC_NO_CHECK_CSV
|
|
73
|
-
|
|
138
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_NO_CHECK_JSON")), INT2FIX(MAGIC_NO_CHECK_JSON)) ;
|
|
74
139
|
#endif
|
|
75
140
|
|
|
76
141
|
return hash ;
|
data/ext/libmagic/params.h
CHANGED
|
@@ -1,28 +1,62 @@
|
|
|
1
1
|
void params(volatile VALUE rb_klass) {
|
|
2
|
+
#ifdef MAGIC_PARAM_INDIR_MAX
|
|
2
3
|
rb_define_const(rb_klass, "MAGIC_PARAM_INDIR_MAX", UINT2NUM(MAGIC_PARAM_INDIR_MAX)) ;
|
|
4
|
+
#endif
|
|
5
|
+
|
|
6
|
+
#ifdef MAGIC_PARAM_NAME_MAX
|
|
3
7
|
rb_define_const(rb_klass, "MAGIC_PARAM_NAME_MAX", UINT2NUM(MAGIC_PARAM_NAME_MAX)) ;
|
|
8
|
+
#endif
|
|
9
|
+
|
|
10
|
+
#ifdef MAGIC_PARAM_ELF_NOTES_MAX
|
|
4
11
|
rb_define_const(rb_klass, "MAGIC_PARAM_ELF_NOTES_MAX", UINT2NUM(MAGIC_PARAM_ELF_NOTES_MAX)) ;
|
|
12
|
+
#endif
|
|
13
|
+
|
|
14
|
+
#ifdef MAGIC_PARAM_ELF_PHNUM_MAX
|
|
5
15
|
rb_define_const(rb_klass, "MAGIC_PARAM_ELF_PHNUM_MAX", UINT2NUM(MAGIC_PARAM_ELF_PHNUM_MAX)) ;
|
|
16
|
+
#endif
|
|
17
|
+
|
|
18
|
+
#ifdef MAGIC_PARAM_ELF_SHNUM_MAX
|
|
6
19
|
rb_define_const(rb_klass, "MAGIC_PARAM_ELF_SHNUM_MAX", UINT2NUM(MAGIC_PARAM_ELF_SHNUM_MAX)) ;
|
|
20
|
+
#endif
|
|
21
|
+
|
|
22
|
+
#ifdef MAGIC_PARAM_REGEX_MAX
|
|
7
23
|
rb_define_const(rb_klass, "MAGIC_PARAM_REGEX_MAX", UINT2NUM(MAGIC_PARAM_REGEX_MAX)) ;
|
|
24
|
+
#endif
|
|
8
25
|
|
|
9
26
|
#ifdef MAGIC_PARAM_BYTES_MAX
|
|
10
|
-
|
|
27
|
+
rb_define_const(rb_klass, "MAGIC_PARAM_BYTES_MAX", UINT2NUM(MAGIC_PARAM_BYTES_MAX)) ;
|
|
11
28
|
#endif
|
|
12
29
|
}
|
|
13
30
|
|
|
14
31
|
VALUE lsparams(volatile VALUE obj) {
|
|
15
32
|
VALUE hash = rb_hash_new() ;
|
|
16
33
|
|
|
34
|
+
#ifdef MAGIC_PARAM_INDIR_MAX
|
|
17
35
|
rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_PARAM_INDIR_MAX")), UINT2NUM(MAGIC_PARAM_INDIR_MAX)) ;
|
|
36
|
+
#endif
|
|
37
|
+
|
|
38
|
+
#ifdef MAGIC_PARAM_NAME_MAX
|
|
18
39
|
rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_PARAM_NAME_MAX")), UINT2NUM(MAGIC_PARAM_NAME_MAX)) ;
|
|
40
|
+
#endif
|
|
41
|
+
|
|
42
|
+
#ifdef MAGIC_PARAM_ELF_NOTES_MAX
|
|
19
43
|
rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_PARAM_ELF_NOTES_MAX")), UINT2NUM(MAGIC_PARAM_ELF_NOTES_MAX)) ;
|
|
44
|
+
#endif
|
|
45
|
+
|
|
46
|
+
#ifdef MAGIC_PARAM_ELF_PHNUM_MAX
|
|
20
47
|
rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_PARAM_ELF_PHNUM_MAX")), UINT2NUM(MAGIC_PARAM_ELF_PHNUM_MAX)) ;
|
|
48
|
+
#endif
|
|
49
|
+
|
|
50
|
+
#ifdef MAGIC_PARAM_ELF_SHNUM_MAX
|
|
21
51
|
rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_PARAM_ELF_SHNUM_MAX")), UINT2NUM(MAGIC_PARAM_ELF_SHNUM_MAX)) ;
|
|
52
|
+
#endif
|
|
53
|
+
|
|
54
|
+
#ifdef MAGIC_PARAM_REGEX_MAX
|
|
22
55
|
rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_PARAM_REGEX_MAX")), UINT2NUM(MAGIC_PARAM_REGEX_MAX)) ;
|
|
56
|
+
#endif
|
|
23
57
|
|
|
24
58
|
#ifdef MAGIC_PARAM_BYTES_MAX
|
|
25
|
-
|
|
59
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_PARAM_BYTES_MAX")), UINT2NUM(MAGIC_PARAM_BYTES_MAX)) ;
|
|
26
60
|
#endif
|
|
27
61
|
|
|
28
62
|
return hash ;
|
data/lib/libmagic_rb/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: libmagic_rb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.2.pre.gamma
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Cybergizer
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2021-
|
|
11
|
+
date: 2021-09-06 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: Check filetype with libmagic
|
|
14
14
|
email:
|