magikku 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.
- data/.document +5 -0
- data/LICENSE +20 -0
- data/README.rdoc +18 -0
- data/Rakefile +61 -0
- data/VERSION +1 -0
- data/ext/magikku_native/extconf.rb +32 -0
- data/ext/magikku_native/magikku_native.c +412 -0
- data/lib/ffi/libmagic.rb +46 -0
- data/lib/magikku/convenience.rb +82 -0
- data/lib/magikku.rb +12 -0
- data/lib/magikku_ffi.rb +278 -0
- data/spec/magikku_behaviors.rb +288 -0
- data/spec/magikku_ffi_spec.rb +30 -0
- data/spec/magikku_spec.rb +10 -0
- data/spec/sample/fail_magicrules +1 -0
- data/spec/sample/rawtestdat.raw +2 -0
- data/spec/sample/ruby_magicrules +16 -0
- data/spec/sample/test.c +6 -0
- data/spec/sample/test.txt +3 -0
- data/spec/sample/test_magicrule +1 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +15 -0
- metadata +114 -0
data/.document
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Eric Monti
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
= ruby-magic
|
2
|
+
|
3
|
+
Ruby bindings for libmagic(3)
|
4
|
+
|
5
|
+
Includes FFI bindings as well as native ruby bindings (the latter is coming soon)..
|
6
|
+
|
7
|
+
== Synopsis
|
8
|
+
|
9
|
+
(coming soon)
|
10
|
+
|
11
|
+
== Installation
|
12
|
+
|
13
|
+
(sudo)? gem install ruby-magic
|
14
|
+
|
15
|
+
|
16
|
+
== Copyright
|
17
|
+
|
18
|
+
Copyright (c) 2011 Eric Monti. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "magikku"
|
8
|
+
gem.summary = "Ruby bindings for the libmagic(3) library"
|
9
|
+
gem.description = "Ruby bindings to the libmagic(3) library for identifying unknown files and data contents"
|
10
|
+
gem.email = "esmonti@gmail.com"
|
11
|
+
gem.homepage = "http://github.com/emonti/magikku"
|
12
|
+
gem.authors = ["Eric Monti"]
|
13
|
+
gem.add_development_dependency "ffi", ">= 0.5.0"
|
14
|
+
gem.add_development_dependency "rspec", ">= 1.2.9"
|
15
|
+
end
|
16
|
+
Jeweler::GemcutterTasks.new
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'spec/rake/spectask'
|
22
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
23
|
+
spec.libs << 'lib' << 'spec'
|
24
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
25
|
+
end
|
26
|
+
|
27
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
28
|
+
spec.libs << 'lib' << 'spec'
|
29
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
30
|
+
spec.rcov = true
|
31
|
+
end
|
32
|
+
|
33
|
+
require 'rake/extensiontask'
|
34
|
+
Rake::ExtensionTask.new("magikku_native")
|
35
|
+
|
36
|
+
CLEAN.include("doc")
|
37
|
+
CLEAN.include("rdoc")
|
38
|
+
CLEAN.include("coverage")
|
39
|
+
CLEAN.include("tmp")
|
40
|
+
CLEAN.include("lib/*.bundle")
|
41
|
+
CLEAN.include("lib/*.so")
|
42
|
+
|
43
|
+
task :spec => [:check_dependencies, :compile]
|
44
|
+
|
45
|
+
task :default => :spec
|
46
|
+
|
47
|
+
require 'rake/rdoctask'
|
48
|
+
Rake::RDocTask.new do |rdoc|
|
49
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
50
|
+
|
51
|
+
rdoc.rdoc_dir = 'rdoc'
|
52
|
+
rdoc.title = "magikku #{version}"
|
53
|
+
rdoc.rdoc_files.include('README*')
|
54
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
55
|
+
rdoc.rdoc_files.include('ext/**/*.c')
|
56
|
+
end
|
57
|
+
|
58
|
+
require 'yard'
|
59
|
+
YARD::Rake::YardocTask.new
|
60
|
+
|
61
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# yara-ruby - Ruby bindings for the yara malware analysis library.
|
2
|
+
# Eric Monti
|
3
|
+
# Copyright (C) 2011 Trustwave Holdings
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify it
|
6
|
+
# under the terms of the GNU General Public License as published by the
|
7
|
+
# Free Software Foundation, either version 3 of the License, or (at your
|
8
|
+
# option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful, but
|
11
|
+
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
12
|
+
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
13
|
+
# for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License along
|
16
|
+
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'mkmf'
|
20
|
+
require 'rbconfig'
|
21
|
+
|
22
|
+
extension_name = "magikku_native"
|
23
|
+
|
24
|
+
dir_config(extension_name)
|
25
|
+
|
26
|
+
unless have_library("magic") and
|
27
|
+
find_header("magic.h", "/usr/local/include")
|
28
|
+
raise "You must install the libmagic library"
|
29
|
+
end
|
30
|
+
|
31
|
+
create_makefile(extension_name)
|
32
|
+
|
@@ -0,0 +1,412 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
#include <magic.h>
|
3
|
+
#include <sys/stat.h>
|
4
|
+
#include <string.h>
|
5
|
+
|
6
|
+
VALUE c_magic = Qnil;
|
7
|
+
VALUE m_flags = Qnil;
|
8
|
+
|
9
|
+
VALUE e_MagikkuError = Qnil;
|
10
|
+
VALUE e_InitFatal = Qnil;
|
11
|
+
VALUE e_DbLoadError = Qnil;
|
12
|
+
VALUE e_CompileError = Qnil;
|
13
|
+
VALUE e_FlagError = Qnil;
|
14
|
+
VALUE e_ClosedError = Qnil;
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
/* Internal function to check whether a handle is already closed */
|
20
|
+
magic_t
|
21
|
+
_check_closed(VALUE self) {
|
22
|
+
magic_t ret = NULL;
|
23
|
+
if (rb_iv_get(self, "@closed") != Qtrue)
|
24
|
+
Data_Get_Struct(self, void, ret);
|
25
|
+
return (magic_t) ret;
|
26
|
+
}
|
27
|
+
|
28
|
+
/* internal MACRO to check for the existence of a file */
|
29
|
+
#define _confirm_file_exists(_filename) \
|
30
|
+
{ struct stat st;\
|
31
|
+
if(stat(_filename, &st) < 0) rb_sys_fail(_filename); }
|
32
|
+
|
33
|
+
#define CLOSED_ERR_MSG "This magic cookie is closed and can no longer be used"
|
34
|
+
|
35
|
+
/* call-seq: Magikku.path() -> "default_magic_db"
|
36
|
+
*
|
37
|
+
* @return String Returns the default magic database path.
|
38
|
+
*/
|
39
|
+
VALUE
|
40
|
+
rb_magic_s_path(VALUE klass) {
|
41
|
+
return rb_str_new2(magic_getpath(NULL, 0));
|
42
|
+
}
|
43
|
+
|
44
|
+
/* call-seq: Magikku.new(params={})
|
45
|
+
*
|
46
|
+
* Instantiates a new Magikku cookie which we can use to load magic databases,
|
47
|
+
* compile new databases, and identify files and string buffers.
|
48
|
+
*
|
49
|
+
* @param Hash params
|
50
|
+
* A hash of optional parameters to pass to the initializer.
|
51
|
+
*
|
52
|
+
* @option params String :db
|
53
|
+
* One or more magic databases to load on initialization. If nothing
|
54
|
+
* is specified, the default database will be used.
|
55
|
+
*
|
56
|
+
* @option params Fixnum :flags
|
57
|
+
* Initialization flags to configure libmagic.
|
58
|
+
*
|
59
|
+
* @see Magikku::Flags and libmagic(3)
|
60
|
+
*
|
61
|
+
* @raise Magikku::DbLoadError
|
62
|
+
* An error is raised if the database cannot be loaded.
|
63
|
+
*
|
64
|
+
* @raise Magikku::InitFatal
|
65
|
+
* An error is raised if an unknown error is encountered initializing
|
66
|
+
* the cookie with libmagic.
|
67
|
+
*/
|
68
|
+
VALUE
|
69
|
+
rb_magic_initialize(int argc, VALUE *argv, VALUE klass) {
|
70
|
+
VALUE params = Qnil;
|
71
|
+
VALUE flags_val, db_val;
|
72
|
+
magic_t cookie;
|
73
|
+
int flags = 0;
|
74
|
+
char *magicf = NULL;
|
75
|
+
const char *error=NULL;
|
76
|
+
|
77
|
+
rb_scan_args(argc, argv, "01", ¶ms);
|
78
|
+
|
79
|
+
if (params != Qnil) {
|
80
|
+
Check_Type(params, T_HASH);
|
81
|
+
|
82
|
+
flags_val=rb_hash_aref(params, ID2SYM(rb_intern("flags")));
|
83
|
+
if (flags_val != Qnil) {
|
84
|
+
Check_Type(flags_val, T_FIXNUM);
|
85
|
+
flags = NUM2INT(flags_val);
|
86
|
+
}
|
87
|
+
|
88
|
+
db_val=rb_hash_aref(params, ID2SYM(rb_intern("db")));
|
89
|
+
if (db_val != Qnil) {
|
90
|
+
Check_Type(db_val, T_STRING);
|
91
|
+
magicf = RSTRING_PTR(db_val);
|
92
|
+
}
|
93
|
+
}
|
94
|
+
|
95
|
+
if ((cookie=magic_open(flags))==NULL)
|
96
|
+
rb_raise(e_InitFatal, "magic_open(%i) returned a null pointer", flags);
|
97
|
+
|
98
|
+
if (magic_load(cookie, magicf) != 0) {
|
99
|
+
error = magic_error(cookie);
|
100
|
+
magic_close(cookie);
|
101
|
+
rb_raise(e_DbLoadError, "Error loading db \"%s\": %s", magicf, error);
|
102
|
+
}
|
103
|
+
|
104
|
+
return Data_Wrap_Struct(klass, NULL, NULL, cookie);
|
105
|
+
}
|
106
|
+
|
107
|
+
|
108
|
+
/* call-seq: dbload(magicfiles) -> true
|
109
|
+
*
|
110
|
+
* Used to load one or more magic databases.
|
111
|
+
*
|
112
|
+
* @param String magicfiles
|
113
|
+
* One or more filenames seperated by colons. If nil, the default database
|
114
|
+
* is loaded.
|
115
|
+
* If uncompiled magic files are specified, they are compiled on the fly
|
116
|
+
* but they do not generate new .mgc files as with the compile method.
|
117
|
+
* Multiple files be specified by seperating them with colons.
|
118
|
+
*
|
119
|
+
* @raise DbLoadError if an error occurred loading the database(s)
|
120
|
+
*
|
121
|
+
* @raise Magikku::CloseError
|
122
|
+
* Raises an error if the Magikku object has been closed.
|
123
|
+
*/
|
124
|
+
VALUE
|
125
|
+
rb_magic_dbload(VALUE self, VALUE magicf_val) {
|
126
|
+
magic_t cookie = _check_closed(self);
|
127
|
+
char *magicf = NULL;
|
128
|
+
|
129
|
+
if(!cookie) rb_raise(e_ClosedError, CLOSED_ERR_MSG);
|
130
|
+
if(magicf_val != Qnil){
|
131
|
+
Check_Type(magicf_val, T_STRING);
|
132
|
+
magicf = RSTRING_PTR(magicf_val);
|
133
|
+
}
|
134
|
+
|
135
|
+
Data_Get_Struct(self, void, cookie);
|
136
|
+
|
137
|
+
if (magic_load(cookie, magicf) != 0)
|
138
|
+
rb_raise(e_DbLoadError, "Error loading db \"%s\": %s", magicf, magic_error(cookie));
|
139
|
+
|
140
|
+
return Qtrue;
|
141
|
+
}
|
142
|
+
|
143
|
+
/* call-seq: close() -> nil
|
144
|
+
*
|
145
|
+
* Close the libmagic data scanner handle when you are finished with it
|
146
|
+
*
|
147
|
+
* Note that magic handles are never closed automatically, even when
|
148
|
+
* garbage collection occurs.
|
149
|
+
*/
|
150
|
+
VALUE
|
151
|
+
rb_magic_close(VALUE self) {
|
152
|
+
magic_t cookie = _check_closed(self);
|
153
|
+
|
154
|
+
if(cookie) magic_close(cookie);
|
155
|
+
rb_iv_set(self, "@closed", Qtrue);
|
156
|
+
|
157
|
+
return Qnil;
|
158
|
+
}
|
159
|
+
|
160
|
+
/* call-seq: closed? -> true|false
|
161
|
+
*
|
162
|
+
* Indicates whether the magic cookie has been closed
|
163
|
+
*
|
164
|
+
* @return true,false
|
165
|
+
*/
|
166
|
+
VALUE
|
167
|
+
rb_magic_is_closed(VALUE self) {
|
168
|
+
VALUE ret = rb_iv_get(self, "@closed");
|
169
|
+
if (ret == Qnil) ret = Qfalse;
|
170
|
+
return ret;
|
171
|
+
}
|
172
|
+
|
173
|
+
/* call-seq: file(filename) -> String
|
174
|
+
*
|
175
|
+
* Identifies file contents using the magicfile database.
|
176
|
+
*
|
177
|
+
* @param String filename
|
178
|
+
* The path to the file to analyze
|
179
|
+
*
|
180
|
+
* @return String
|
181
|
+
* A textual description of the contents of the file
|
182
|
+
*
|
183
|
+
* @raise Magikku::CloseError
|
184
|
+
* Raises an error if the Magikku object has been closed.
|
185
|
+
*/
|
186
|
+
VALUE
|
187
|
+
rb_magic_file(VALUE self, VALUE filename) {
|
188
|
+
magic_t cookie = _check_closed(self);
|
189
|
+
if (cookie) {
|
190
|
+
char * fname;
|
191
|
+
struct stat st;
|
192
|
+
|
193
|
+
Check_Type(filename, T_STRING);
|
194
|
+
fname = RSTRING_PTR(filename);
|
195
|
+
|
196
|
+
if(stat(fname, &st) < 0)
|
197
|
+
rb_sys_fail(fname);
|
198
|
+
|
199
|
+
return rb_str_new2(magic_file(cookie, fname));
|
200
|
+
|
201
|
+
} else {
|
202
|
+
rb_raise(e_ClosedError, CLOSED_ERR_MSG);
|
203
|
+
}
|
204
|
+
|
205
|
+
}
|
206
|
+
|
207
|
+
/* call-seq: string(buf) -> String
|
208
|
+
*
|
209
|
+
* Identifies string contents using the magicfile database.
|
210
|
+
*
|
211
|
+
* @param String buf
|
212
|
+
* The string to analyze.
|
213
|
+
*
|
214
|
+
* @return String
|
215
|
+
* A textual description of the contents of the string
|
216
|
+
*
|
217
|
+
* @raise Magikku::CloseError
|
218
|
+
* Raises an error if the Magikku object has been closed.
|
219
|
+
*/
|
220
|
+
VALUE rb_magic_string(VALUE self, VALUE string) {
|
221
|
+
const char *ret;
|
222
|
+
magic_t cookie = _check_closed(self);
|
223
|
+
if (!cookie) rb_raise(e_ClosedError, CLOSED_ERR_MSG);
|
224
|
+
Check_Type(string, T_STRING);
|
225
|
+
|
226
|
+
ret=magic_buffer(cookie, RSTRING_PTR(string), RSTRING_LEN(string));
|
227
|
+
return rb_str_new2(ret);
|
228
|
+
}
|
229
|
+
|
230
|
+
/* call-seq: compile(filename=nil)
|
231
|
+
*
|
232
|
+
* Can be used to compile magic files. This does not load files, however. You must
|
233
|
+
* use dbload for that.
|
234
|
+
*
|
235
|
+
* Note: Errors and warnings may be displayed on stderr.
|
236
|
+
*
|
237
|
+
* @param String,nil filename
|
238
|
+
* A colon seperated list of filenames or a single filename.
|
239
|
+
* The compiled files created are generated in the current directory using
|
240
|
+
* the basename(1) of each file argument with ".mgc" appended to it.
|
241
|
+
* Directory names can be compiled, in which case the contents of the
|
242
|
+
* directory will be compiled together as a single .mgc file.
|
243
|
+
* nil compiles the default database.
|
244
|
+
*
|
245
|
+
* @return true if everything went well.
|
246
|
+
*
|
247
|
+
* @raise CompileError if an error occurred.
|
248
|
+
*/
|
249
|
+
VALUE rb_magic_compile(VALUE self, VALUE magicf) {
|
250
|
+
char *_magicf;
|
251
|
+
magic_t cookie = _check_closed(self);
|
252
|
+
|
253
|
+
if (!cookie) rb_raise(e_ClosedError, CLOSED_ERR_MSG);
|
254
|
+
if (magicf != Qnil) Check_Type(magicf, T_STRING);
|
255
|
+
|
256
|
+
_magicf = RSTRING_PTR(magicf);
|
257
|
+
|
258
|
+
if (magic_compile(cookie, _magicf) == 0) return Qtrue;
|
259
|
+
else rb_raise(e_CompileError,
|
260
|
+
"Error compiling \"%s\": %s", _magicf, magic_error(cookie));
|
261
|
+
}
|
262
|
+
|
263
|
+
/* call-seq: magic.check_syntax("some_magic_db") -> (true|false)
|
264
|
+
*
|
265
|
+
* Can be used to check the validity of magic files before compiling them.
|
266
|
+
* This is basically a dry-run that can be used before compiling magicfile
|
267
|
+
* databases.
|
268
|
+
*
|
269
|
+
* Note: Errors and warnings may be displayed on stderr.
|
270
|
+
*
|
271
|
+
* @param String,nil filename
|
272
|
+
* A colon seperated list of filenames or a single file. nil checks the
|
273
|
+
* default database.
|
274
|
+
*
|
275
|
+
* @return true,false Indicates whether the check was successful.
|
276
|
+
*/
|
277
|
+
VALUE rb_magic_check_syntax(VALUE self, VALUE rb_magicf) {
|
278
|
+
magic_t cookie = _check_closed(self);
|
279
|
+
char * magicf = NULL;
|
280
|
+
|
281
|
+
if (!cookie) rb_raise(e_ClosedError, CLOSED_ERR_MSG);
|
282
|
+
if (rb_magicf != Qnil) {
|
283
|
+
Check_Type(rb_magicf, T_STRING);
|
284
|
+
magicf = RSTRING_PTR(rb_magicf);
|
285
|
+
}
|
286
|
+
|
287
|
+
if (magic_check(cookie, magicf) == 0) return Qtrue;
|
288
|
+
else return Qfalse;
|
289
|
+
}
|
290
|
+
|
291
|
+
/* call-seq: magic.flags = (Magikku::Flags::MIME | Magikku::Flags::DEBUG)
|
292
|
+
*
|
293
|
+
* Sets libmagic flags on the object. See Magikku::Flags
|
294
|
+
*
|
295
|
+
* @raise Magikku::CloseError
|
296
|
+
* Raises an error if the Magikku object has been closed.
|
297
|
+
*/
|
298
|
+
VALUE rb_magic_set_flags(VALUE self, VALUE flags) {
|
299
|
+
magic_t cookie = _check_closed(self);
|
300
|
+
|
301
|
+
Check_Type(flags, T_FIXNUM);
|
302
|
+
|
303
|
+
if(magic_setflags(cookie, NUM2INT(flags)) < 0)
|
304
|
+
rb_raise(e_FlagError, magic_error(cookie));
|
305
|
+
|
306
|
+
return flags;
|
307
|
+
}
|
308
|
+
|
309
|
+
void Init_magikku_native() {
|
310
|
+
/* The Magikku class is both our interface to libmagic functionality
|
311
|
+
as well as the top-level namespace */
|
312
|
+
c_magic = rb_define_class("Magikku", rb_cObject);
|
313
|
+
rb_define_singleton_method(c_magic, "path", rb_magic_s_path, 0);
|
314
|
+
// rb_define_singleton_method(c_magic, "compile", rb_magic_s_compile, 1);
|
315
|
+
// rb_define_singleton_method(c_magic, "check_syntax", rb_magic_s_check_syntax, 1);
|
316
|
+
|
317
|
+
rb_define_singleton_method(c_magic, "new", rb_magic_initialize, -1);
|
318
|
+
|
319
|
+
rb_define_method(c_magic, "close", rb_magic_close, 0);
|
320
|
+
rb_define_method(c_magic, "closed?", rb_magic_is_closed, 0);
|
321
|
+
rb_define_method(c_magic, "compile", rb_magic_compile, 1);
|
322
|
+
rb_define_method(c_magic, "check_syntax", rb_magic_check_syntax, 1);
|
323
|
+
rb_define_method(c_magic, "file", rb_magic_file, 1);
|
324
|
+
rb_define_method(c_magic, "string", rb_magic_string, 1);
|
325
|
+
rb_define_method(c_magic, "flags=", rb_magic_set_flags, 1);
|
326
|
+
rb_define_method(c_magic, "dbload", rb_magic_dbload, 1);
|
327
|
+
|
328
|
+
/* Defines various flags that can be passed when creating a magic scanning
|
329
|
+
* object using Magikku.new with the :flags parameter or after instantiation
|
330
|
+
* using Magikku.flags= .
|
331
|
+
*
|
332
|
+
* Available flags are as follows:
|
333
|
+
*
|
334
|
+
* NONE No flags
|
335
|
+
* DEBUG Turn on debugging
|
336
|
+
* SYMLINK Follow symlinks
|
337
|
+
* COMPRESS Check inside compressed files
|
338
|
+
* DEVICES Look at the contents of devices
|
339
|
+
* MIME_TYPE Return the MIME type
|
340
|
+
* CONTINUE Return all matches
|
341
|
+
* CHECK Print warnings to stderr
|
342
|
+
* PRESERVE_ATIME Restore access time on exit
|
343
|
+
* RAW Don't translate unprintable chars
|
344
|
+
* ERROR Handle ENOENT etc as real errors
|
345
|
+
* MIME_ENCODING Return the MIME encoding
|
346
|
+
* MIME Alias for (MIME_TYPE|MIME_ENCODING)
|
347
|
+
* APPLE Return the Apple creator and type
|
348
|
+
* NO_CHECK_COMPRESS Don't check for compressed files
|
349
|
+
* NO_CHECK_TAR Don't check for tar files
|
350
|
+
* NO_CHECK_SOFT Don't check magic entries
|
351
|
+
* NO_CHECK_APPTYPE Don't check application type
|
352
|
+
* NO_CHECK_ELF Don't check for elf details
|
353
|
+
* NO_CHECK_TEXT Don't check for text files
|
354
|
+
* NO_CHECK_CDF Don't check for cdf files
|
355
|
+
* NO_CHECK_TOKENS Don't check tokens
|
356
|
+
* NO_CHECK_ENCODING Don't check text encodings
|
357
|
+
* NO_CHECK_ASCII Alias for NO_CHECK_TEXT
|
358
|
+
*
|
359
|
+
* @see libmagic(3)
|
360
|
+
*
|
361
|
+
*/
|
362
|
+
m_flags = rb_define_module_under(c_magic, "Flags");
|
363
|
+
rb_define_const(m_flags, "NONE", INT2FIX(MAGIC_NONE));
|
364
|
+
rb_define_const(m_flags, "DEBUG", INT2FIX(MAGIC_DEBUG));
|
365
|
+
rb_define_const(m_flags, "SYMLINK", INT2FIX(MAGIC_SYMLINK));
|
366
|
+
rb_define_const(m_flags, "COMPRESS", INT2FIX(MAGIC_COMPRESS));
|
367
|
+
rb_define_const(m_flags, "DEVICES", INT2FIX(MAGIC_DEVICES));
|
368
|
+
rb_define_const(m_flags, "MIME_TYPE", INT2FIX(MAGIC_MIME_TYPE));
|
369
|
+
rb_define_const(m_flags, "CONTINUE", INT2FIX(MAGIC_CONTINUE));
|
370
|
+
rb_define_const(m_flags, "CHECK", INT2FIX(MAGIC_CHECK));
|
371
|
+
rb_define_const(m_flags, "PRESERVE_ATIME", INT2FIX(MAGIC_PRESERVE_ATIME));
|
372
|
+
rb_define_const(m_flags, "RAW", INT2FIX(MAGIC_RAW));
|
373
|
+
rb_define_const(m_flags, "ERROR", INT2FIX(MAGIC_ERROR));
|
374
|
+
rb_define_const(m_flags, "MIME_ENCODING", INT2FIX(MAGIC_MIME_ENCODING));
|
375
|
+
rb_define_const(m_flags, "MIME", INT2FIX(MAGIC_MIME));
|
376
|
+
rb_define_const(m_flags, "APPLE", INT2FIX(MAGIC_APPLE));
|
377
|
+
rb_define_const(m_flags, "NO_CHECK_COMPRESS", INT2FIX(MAGIC_NO_CHECK_COMPRESS));
|
378
|
+
rb_define_const(m_flags, "NO_CHECK_TAR", INT2FIX(MAGIC_NO_CHECK_TAR));
|
379
|
+
rb_define_const(m_flags, "NO_CHECK_SOFT", INT2FIX(MAGIC_NO_CHECK_SOFT));
|
380
|
+
rb_define_const(m_flags, "NO_CHECK_APPTYPE", INT2FIX(MAGIC_NO_CHECK_APPTYPE));
|
381
|
+
rb_define_const(m_flags, "NO_CHECK_ELF", INT2FIX(MAGIC_NO_CHECK_ELF));
|
382
|
+
rb_define_const(m_flags, "NO_CHECK_TEXT", INT2FIX(MAGIC_NO_CHECK_TEXT));
|
383
|
+
rb_define_const(m_flags, "NO_CHECK_CDF", INT2FIX(MAGIC_NO_CHECK_CDF));
|
384
|
+
rb_define_const(m_flags, "NO_CHECK_TOKENS", INT2FIX(MAGIC_NO_CHECK_TOKENS));
|
385
|
+
rb_define_const(m_flags, "NO_CHECK_ENCODING", INT2FIX(MAGIC_NO_CHECK_ENCODING));
|
386
|
+
rb_define_const(m_flags, "NO_CHECK_ASCII", INT2FIX(MAGIC_NO_CHECK_ASCII));
|
387
|
+
|
388
|
+
/* define our exception classes... */
|
389
|
+
|
390
|
+
/* A base class for other Magikku error types */
|
391
|
+
e_MagikkuError = rb_define_class_under(c_magic, "MagikkuError", rb_eStandardError);
|
392
|
+
|
393
|
+
/* InitFatal is raised for unexpected errors initializing Magikku */
|
394
|
+
e_InitFatal = rb_define_class_under(c_magic, "InitFatal", e_MagikkuError);
|
395
|
+
|
396
|
+
/* DbLoadError is raised when an error occurs loading a magic database */
|
397
|
+
e_DbLoadError = rb_define_class_under(c_magic, "DbLoadError", e_MagikkuError);
|
398
|
+
|
399
|
+
/* CompileError is raised when an error occurs compiling a magic database */
|
400
|
+
e_CompileError = rb_define_class_under(c_magic, "CompileError", e_MagikkuError);
|
401
|
+
|
402
|
+
/* FlagError is raised when an error occurs compiling setting flags
|
403
|
+
*
|
404
|
+
* This is only known to happen on systems that don't support utime(2), or
|
405
|
+
* utimes(2) when Magikku::Flag::PRESERVE_ATIME is set
|
406
|
+
*/
|
407
|
+
e_FlagError = rb_define_class_under(c_magic, "FlagError", e_MagikkuError);
|
408
|
+
|
409
|
+
/* ClosedError is raised if an operation is called on a closed Magikku object */
|
410
|
+
e_ClosedError = rb_define_class_under(c_magic, "ClosedError", e_MagikkuError);
|
411
|
+
|
412
|
+
}
|
data/lib/ffi/libmagic.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
|
3
|
+
module FFI
|
4
|
+
module Libmagic
|
5
|
+
extend FFI::Library
|
6
|
+
ffi_lib 'magic'
|
7
|
+
|
8
|
+
typedef :pointer, :magic_t
|
9
|
+
|
10
|
+
# magic_t magic_open(int flags);
|
11
|
+
attach_function :magic_open, [:int], :magic_t
|
12
|
+
|
13
|
+
# void magic_close(magic_t cookie);
|
14
|
+
attach_function :magic_close, [:magic_t], :void
|
15
|
+
|
16
|
+
# const char * magic_error(magic_t cookie);
|
17
|
+
attach_function :magic_error, [:magic_t], :string
|
18
|
+
|
19
|
+
# int magic_errno(magic_t cookie);
|
20
|
+
attach_function :magic_errno, [:magic_t], :int
|
21
|
+
|
22
|
+
# const char * magic_file(magic_t cookie, const char *filename);
|
23
|
+
attach_function :magic_file, [:magic_t, :string], :string
|
24
|
+
|
25
|
+
# const char * magic_buffer(magic_t cookie, const void *buffer, size_t length);
|
26
|
+
attach_function :magic_buffer, [:magic_t, :pointer, :size_t], :string
|
27
|
+
|
28
|
+
# int magic_setflags(magic_t cookie, int flags);
|
29
|
+
attach_function :magic_setflags, [:magic_t, :int], :int
|
30
|
+
|
31
|
+
# int magic_check(magic_t cookie, const char *filename);
|
32
|
+
attach_function :magic_check, [:magic_t, :string], :int
|
33
|
+
|
34
|
+
# int magic_compile(magic_t cookie, const char *filename);
|
35
|
+
attach_function :magic_compile, [:magic_t, :string], :int
|
36
|
+
|
37
|
+
# int magic_load(magic_t cookie, const char *filename);
|
38
|
+
attach_function :magic_load, [:magic_t, :string], :int
|
39
|
+
|
40
|
+
# NOTE magic_getpath not doc'd in libmagic(3),
|
41
|
+
# not available in earlier versions?
|
42
|
+
#
|
43
|
+
# const char * int magic_getpath(const char *magicfile, int action)
|
44
|
+
attach_function :magic_getpath, [:string, :int], :string
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
|
2
|
+
module MagikkuHelpers
|
3
|
+
# A convenience method for checking syntax of magicdb files.
|
4
|
+
#
|
5
|
+
# Note: syntax errors and warnings may be displayed on stderr.
|
6
|
+
#
|
7
|
+
# @param String fname
|
8
|
+
# Filename or directory to compile
|
9
|
+
#
|
10
|
+
# @param Hash params
|
11
|
+
# A hash of parameters to Magikku.new()
|
12
|
+
#
|
13
|
+
# @return true,false
|
14
|
+
def check_syntax(fname, params={})
|
15
|
+
m=new(params)
|
16
|
+
begin
|
17
|
+
return m.check_syntax(fname)
|
18
|
+
ensure
|
19
|
+
m.close()
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# A convenience method for compiling magicdb files.
|
24
|
+
#
|
25
|
+
# @param String fname
|
26
|
+
# Filename or directory to compile
|
27
|
+
#
|
28
|
+
# @param Hash params
|
29
|
+
# A hash of parameters to Magikku.new()
|
30
|
+
#
|
31
|
+
# @return true
|
32
|
+
#
|
33
|
+
# @raise Magikku::CompileError if an error occurs
|
34
|
+
def compile(fname, params={})
|
35
|
+
m=new(params)
|
36
|
+
begin
|
37
|
+
return m.compile(fname)
|
38
|
+
ensure
|
39
|
+
m.close()
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# A convenience method for identifying file contents
|
44
|
+
#
|
45
|
+
# @param String fname
|
46
|
+
# Filename to identify
|
47
|
+
#
|
48
|
+
# @param Hash params
|
49
|
+
# A hash of parameters to Magikku.new()
|
50
|
+
#
|
51
|
+
# @return String
|
52
|
+
# Identification of the file contents.
|
53
|
+
def file(fname, params={})
|
54
|
+
m=new(params)
|
55
|
+
begin
|
56
|
+
return m.file(fname)
|
57
|
+
ensure
|
58
|
+
m.close()
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# A convenience method for identifying string contents
|
63
|
+
#
|
64
|
+
# @param String buf
|
65
|
+
# String contents to identify
|
66
|
+
#
|
67
|
+
# @param Hash params
|
68
|
+
# A hash of parameters to Magikku.new()
|
69
|
+
#
|
70
|
+
# @return String
|
71
|
+
# Identification of the string.
|
72
|
+
def string(buf, params={})
|
73
|
+
m=new(params)
|
74
|
+
begin
|
75
|
+
return m.string(buf)
|
76
|
+
ensure
|
77
|
+
m.close()
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
|