ruby-filemagic 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,28 @@
1
+ --------------------------------------------------------------------------------
2
+ 7/28/2003 version 0.1.0
3
+
4
+ o Initial release.
5
+
6
+ --------------------------------------------------------------------------------
7
+ 7/30/2003 version 0.1.1
8
+
9
+ o Added manual close method
10
+ o Added unit test suite
11
+
12
+ --------------------------------------------------------------------------------
13
+ 9/12/2008 version 0.2.0
14
+
15
+ o Modified C API
16
+ o Uniform C function prefix rb_magic_ (instead of magick_)
17
+ o Uniform Ruby method prefix fm_ (instead of none)
18
+ o More magic(4) constants (if available)
19
+ o Added Ruby wrapper for more rubyish interface
20
+ o Added extensions for File and String core classes
21
+ o Added/updated project files
22
+ o Now available as a Rubygem!
23
+
24
+ --------------------------------------------------------------------------------
25
+ 9/18/2008 version 0.2.1
26
+
27
+ o Added mahoro source file and tests for reference and inspiration
28
+ o We have a Rubyforge project now! :-)
data/README ADDED
@@ -0,0 +1,69 @@
1
+ = FileMagic Library Binding
2
+
3
+ == VERSION
4
+
5
+ This documentation refers to filemagic version 0.2.1
6
+
7
+
8
+ == DESCRIPTION
9
+
10
+ === Revised version
11
+
12
+ September 12, 2008 Jens Wille <jens.wille@uni-koeln.de>
13
+
14
+ Similar to Ricardo[http://github.com/ricardochimal/ruby-filemagic]
15
+ I wanted this project to make some progress. My needs went a bit
16
+ farther than his, though ;-) Enjoy anyway!
17
+
18
+ Install the gem from github[http://github.com]:
19
+
20
+ sudo gem install blackwinter-ruby-filemagic --source http://gems.github.com
21
+
22
+ === Original package
23
+
24
+ July 28, 2003 Travis Whitton <tinymountain@gmail.com>
25
+
26
+ This is one of my first ruby bindings, so suggestions are welcome. See
27
+ filemagic.rd and test.rb for usage.
28
+
29
+ to install, run these commands:
30
+
31
+ ruby extconf.rb
32
+ make
33
+ su
34
+ make install
35
+
36
+ the file(1) library and headers are required.
37
+ I have file 0.4.3.
38
+
39
+ Enjoy!
40
+ Travis
41
+
42
+
43
+ == LINKS
44
+
45
+ * <http://grub.ath.cx/filemagic/>
46
+ * <http://github.com/blackwinter/ruby-filemagic>
47
+ * <http://ruby-filemagic.rubyforge.org/>
48
+ * <http://rubyforge.org/projects/ruby-filemagic>
49
+
50
+
51
+ == AUTHORS
52
+
53
+ * Travis Whitton <mailto:tinymountain@gmail.com> (Original author)
54
+ * Jens Wille <mailto:jens.wille@uni-koeln.de>
55
+
56
+
57
+ == COPYING
58
+
59
+ The filemagic extension library is copywrited free software by Travis Whitton
60
+ <tinymountain@gmail.com>. You can redistribute it under the terms specified in
61
+ the COPYING file of the Ruby distribution.
62
+
63
+
64
+ == WARRANTY
65
+
66
+ THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
67
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
68
+ WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
69
+ PURPOSE.
@@ -0,0 +1,26 @@
1
+ require %q{lib/filemagic/version}
2
+
3
+ begin
4
+ require 'hen'
5
+
6
+ Hen.lay! {{
7
+ :rubyforge => {
8
+ :package => 'ruby-filemagic',
9
+ :project => 'ruby-filemagic',
10
+ :rdoc_dir => nil
11
+ },
12
+
13
+ :gem => {
14
+ :version => FileMagic::VERSION,
15
+ :summary => 'Ruby bindings to the magic(4) library',
16
+ :authors => ['Travis Whitton', 'Jens Wille'],
17
+ :email => ['tinymountain@gmail.com', 'jens.wille@uni-koeln.de'],
18
+ :homepage => 'http://ruby-filemagic.rubyforge.org/',
19
+ :files => FileList['lib/**/*.rb', 'ext/**/*.c', 'test/*'].to_a,
20
+ :extensions => FileList['ext/**/extconf.rb'].to_a,
21
+ :extra_files => FileList['[A-Z]*', 'info/*'].to_a
22
+ }
23
+ }}
24
+ rescue LoadError
25
+ abort "Please install the 'hen' gem first."
26
+ end
data/TODO ADDED
@@ -0,0 +1,9 @@
1
+ o Find a better way to handle magic_load than just defaulting to NULL
2
+ o Find a way to make magic_check work on NULL
3
+ o [DONE] Find a way to make magic_setflags work
4
+ o Refactor code into initialize instead of new
5
+ o [DONE?] Enable blocks for automatic cleanup:
6
+
7
+ FileMagic.open("somefile.txt") do |file|
8
+ # close is called at the end of this block
9
+ end
@@ -0,0 +1,8 @@
1
+ require 'mkmf'
2
+
3
+ dir_config("magic")
4
+ if have_library("magic", "magic_open") and have_header("magic.h")
5
+ create_makefile("filemagic")
6
+ else
7
+ print "*** ERROR: missing required library to compile this module\n"
8
+ end
@@ -0,0 +1,213 @@
1
+ /*********************************************************
2
+
3
+ filemagic.c
4
+
5
+ a Ruby extension to bind Ruby to the libmagic library
6
+ (ftp://ftp.astron.com/pub/file/)
7
+
8
+ patterned very closely off of audiofile.c by jaredj which
9
+ is patterned very very closely off of gdbm.c by matz ;-)
10
+
11
+ $Author: twhitton $
12
+ $Date: 2003/07/30 13:25:10 $
13
+
14
+ *********************************************************/
15
+
16
+ #include "ruby.h"
17
+ #include <magic.h>
18
+
19
+ static VALUE cFileMagic, rb_FileMagicError;
20
+
21
+ #define GetMagicCookie(obj, cookie) {\
22
+ if (rb_funcall(obj, rb_intern("closed?"), 0))\
23
+ rb_raise(rb_eRuntimeError, "closed stream");\
24
+ Data_Get_Struct(obj, struct magic_set, cookie);\
25
+ }
26
+
27
+ /*
28
+ GC never seems to happen until the program terminates, but this is called
29
+ on any unclosed objects
30
+ */
31
+ static void rb_magic_free(magic_t cookie) {
32
+ magic_close(cookie);
33
+ }
34
+
35
+ static VALUE rb_magic_init(VALUE self, VALUE flags) {
36
+ }
37
+
38
+ /* Frees resources allocated */
39
+ static VALUE rb_magic_close(VALUE self) {
40
+ magic_t cookie;
41
+
42
+ GetMagicCookie(self, cookie);
43
+ magic_close(cookie);
44
+
45
+ /* This keeps rb_magic_free from trying to free closed objects */
46
+ RDATA(self)->data = NULL;
47
+
48
+ return Qnil;
49
+ }
50
+
51
+ /* FileMagic.new */
52
+ static VALUE rb_magic_new(VALUE class, VALUE flags) {
53
+ VALUE obj;
54
+ magic_t cookie;
55
+
56
+ cookie = magic_open(NUM2INT(flags));
57
+ if (cookie == NULL)
58
+ rb_fatal("out of memory");
59
+ if (magic_load(cookie, NULL) == -1)
60
+ rb_fatal("%s", magic_error(cookie));
61
+
62
+ obj = Data_Wrap_Struct(class, 0, rb_magic_free, cookie);
63
+ rb_obj_call_init(obj, 1, &flags);
64
+
65
+ return obj;
66
+ }
67
+
68
+ /* Return a string describing file */
69
+ static VALUE rb_magic_file(VALUE self, VALUE file) {
70
+ const char *m;
71
+ magic_t cookie;
72
+
73
+ m = STR2CSTR(file);
74
+ GetMagicCookie(self, cookie);
75
+ if ((m = magic_file(cookie, m)) == NULL)
76
+ rb_raise(rb_FileMagicError, magic_error(cookie));
77
+
78
+ return rb_str_new2(m);
79
+ }
80
+
81
+ /* Return a string describing the string buffer */
82
+ static VALUE rb_magic_buffer(VALUE self, VALUE buffer) {
83
+ int i = RSTRING(buffer)->len;
84
+ const char *m;
85
+ magic_t cookie;
86
+
87
+ m = STR2CSTR(buffer);
88
+ GetMagicCookie(self, cookie);
89
+ if ((m = magic_buffer(cookie, m, i)) == NULL)
90
+ rb_raise(rb_FileMagicError, magic_error(cookie));
91
+
92
+ return rb_str_new2(m);
93
+ }
94
+
95
+ /* Set flags on the cookie object */
96
+ static VALUE rb_magic_setflags(VALUE self, VALUE flags) {
97
+ int retval;
98
+ magic_t cookie;
99
+
100
+ GetMagicCookie(self, cookie);
101
+ retval = magic_setflags(cookie, NUM2INT(flags));
102
+
103
+ return INT2FIX(retval);
104
+ }
105
+
106
+ /* Checks validity of a magic database file */
107
+ static VALUE rb_magic_check(VALUE self, VALUE file) {
108
+ int retval;
109
+ const char *m;
110
+ magic_t cookie;
111
+
112
+ GetMagicCookie(self, cookie);
113
+ m = STR2CSTR(file);
114
+ retval = magic_check(cookie, m);
115
+
116
+ return INT2FIX(retval);
117
+ }
118
+
119
+ /* Compiles a magic database file */
120
+ static VALUE rb_magic_compile(VALUE self, VALUE file) {
121
+ int retval;
122
+ const char *m;
123
+ magic_t cookie;
124
+
125
+ GetMagicCookie(self, cookie);
126
+ m = STR2CSTR(file);
127
+ retval = magic_compile(cookie, m);
128
+
129
+ return INT2FIX(retval);
130
+ }
131
+
132
+ void Init_filemagic() {
133
+ cFileMagic = rb_define_class("FileMagic", rb_cObject);
134
+
135
+ rb_define_singleton_method(cFileMagic, "fm_new", rb_magic_new, 1);
136
+
137
+ rb_define_method(cFileMagic, "fm_initialize", rb_magic_init, 1);
138
+ rb_define_method(cFileMagic, "fm_close", rb_magic_close, 0);
139
+ rb_define_method(cFileMagic, "fm_file", rb_magic_file, 1);
140
+ rb_define_method(cFileMagic, "fm_buffer", rb_magic_buffer, 1);
141
+ rb_define_method(cFileMagic, "fm_setflags", rb_magic_setflags, 1);
142
+ rb_define_method(cFileMagic, "fm_check", rb_magic_check, 1);
143
+ rb_define_method(cFileMagic, "fm_compile", rb_magic_compile, 1);
144
+
145
+ rb_FileMagicError = rb_define_class_under(cFileMagic, "FileMagicError", rb_eStandardError);
146
+
147
+ #ifdef MAGIC_NONE
148
+ rb_define_const(cFileMagic, "MAGIC_NONE", INT2FIX(MAGIC_NONE));
149
+ #endif
150
+ #ifdef MAGIC_DEBUG
151
+ rb_define_const(cFileMagic, "MAGIC_DEBUG", INT2FIX(MAGIC_DEBUG));
152
+ #endif
153
+ #ifdef MAGIC_SYMLINK
154
+ rb_define_const(cFileMagic, "MAGIC_SYMLINK", INT2FIX(MAGIC_SYMLINK));
155
+ #endif
156
+ #ifdef MAGIC_COMPRESS
157
+ rb_define_const(cFileMagic, "MAGIC_COMPRESS", INT2FIX(MAGIC_COMPRESS));
158
+ #endif
159
+ #ifdef MAGIC_DEVICES
160
+ rb_define_const(cFileMagic, "MAGIC_DEVICES", INT2FIX(MAGIC_DEVICES));
161
+ #endif
162
+ #ifdef MAGIC_MIME_TYPE
163
+ rb_define_const(cFileMagic, "MAGIC_MIME_TYPE", INT2FIX(MAGIC_MIME_TYPE));
164
+ #endif
165
+ #ifdef MAGIC_CONTINUE
166
+ rb_define_const(cFileMagic, "MAGIC_CONTINUE", INT2FIX(MAGIC_CONTINUE));
167
+ #endif
168
+ #ifdef MAGIC_CHECK
169
+ rb_define_const(cFileMagic, "MAGIC_CHECK", INT2FIX(MAGIC_CHECK));
170
+ #endif
171
+ #ifdef MAGIC_PRESERVE_ATIME
172
+ rb_define_const(cFileMagic, "MAGIC_PRESERVE_ATIME", INT2FIX(MAGIC_PRESERVE_ATIME));
173
+ #endif
174
+ #ifdef MAGIC_RAW
175
+ rb_define_const(cFileMagic, "MAGIC_RAW", INT2FIX(MAGIC_RAW));
176
+ #endif
177
+ #ifdef MAGIC_ERROR
178
+ rb_define_const(cFileMagic, "MAGIC_ERROR", INT2FIX(MAGIC_ERROR));
179
+ #endif
180
+ #ifdef MAGIC_MIME_ENCODING
181
+ rb_define_const(cFileMagic, "MAGIC_MIME_ENCODING", INT2FIX(MAGIC_MIME_ENCODING));
182
+ #endif
183
+ #ifdef MAGIC_MIME
184
+ rb_define_const(cFileMagic, "MAGIC_MIME", INT2FIX(MAGIC_MIME));
185
+ #endif
186
+ #ifdef MAGIC_NO_CHECK_COMPRESS
187
+ rb_define_const(cFileMagic, "MAGIC_NO_CHECK_COMPRESS", INT2FIX(MAGIC_NO_CHECK_COMPRESS));
188
+ #endif
189
+ #ifdef MAGIC_NO_CHECK_TAR
190
+ rb_define_const(cFileMagic, "MAGIC_NO_CHECK_TAR", INT2FIX(MAGIC_NO_CHECK_TAR));
191
+ #endif
192
+ #ifdef MAGIC_NO_CHECK_SOFT
193
+ rb_define_const(cFileMagic, "MAGIC_NO_CHECK_SOFT", INT2FIX(MAGIC_NO_CHECK_SOFT));
194
+ #endif
195
+ #ifdef MAGIC_NO_CHECK_APPTYPE
196
+ rb_define_const(cFileMagic, "MAGIC_NO_CHECK_APPTYPE", INT2FIX(MAGIC_NO_CHECK_APPTYPE));
197
+ #endif
198
+ #ifdef MAGIC_NO_CHECK_ELF
199
+ rb_define_const(cFileMagic, "MAGIC_NO_CHECK_ELF", INT2FIX(MAGIC_NO_CHECK_ELF));
200
+ #endif
201
+ #ifdef MAGIC_NO_CHECK_ASCII
202
+ rb_define_const(cFileMagic, "MAGIC_NO_CHECK_ASCII", INT2FIX(MAGIC_NO_CHECK_ASCII));
203
+ #endif
204
+ #ifdef MAGIC_NO_CHECK_TROFF
205
+ rb_define_const(cFileMagic, "MAGIC_NO_CHECK_TROFF", INT2FIX(MAGIC_NO_CHECK_TROFF));
206
+ #endif
207
+ #ifdef MAGIC_NO_CHECK_TOKENS
208
+ rb_define_const(cFileMagic, "MAGIC_NO_CHECK_TOKENS", INT2FIX(MAGIC_NO_CHECK_TOKENS));
209
+ #endif
210
+ #ifdef MAGIC_NO_CHECK_FORTRAN
211
+ rb_define_const(cFileMagic, "MAGIC_NO_CHECK_FORTRAN", INT2FIX(MAGIC_NO_CHECK_FORTRAN));
212
+ #endif
213
+ }
@@ -0,0 +1,28 @@
1
+ #! /usr/bin/ruby
2
+
3
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
4
+ require 'filemagic'
5
+
6
+ puts FileMagic.new.flags
7
+
8
+ FileMagic.open(:mime) { |fm|
9
+ puts fm.flags
10
+ puts fm.file(__FILE__)
11
+
12
+ fm.setflags(:raw, :continue)
13
+ puts fm.flags
14
+ }
15
+
16
+ fm = FileMagic.new
17
+ puts fm.flags
18
+
19
+ mime = FileMagic.mime
20
+ puts mime.flags
21
+
22
+ ARGV.each { |file|
23
+ puts fm.file(file)
24
+ puts fm.file(file, true)
25
+
26
+ puts mime.file(file)
27
+ puts mime.file(file, true)
28
+ }
@@ -0,0 +1,36 @@
1
+ =begin
2
+
3
+ = FileMagic extension module SEE ALSO libmagic(3), file(1) and magic(4)
4
+ == FileMagic
5
+ === Constants
6
+ : MAGIC_NONE
7
+ No flags
8
+ : MAGIC_DEBUG
9
+ Turn on debuggin
10
+ : MAGIC_SYMLINK
11
+ Follow symlinks
12
+ : MAGIC_COMPRESS
13
+ Check inside compressed files
14
+ : MAGIC_DEVICES
15
+ Look at the contents of devices
16
+ : MAGIC_MIME
17
+ Return a mime string
18
+ : MAGIC_CONTINUE
19
+ Return all matches, not just the first
20
+ : MAGIC_CHECK
21
+ Print warnings to stderr
22
+
23
+ === Methods
24
+ : file(filename)
25
+ returns a textual description of the contents of the filename argument
26
+ : buffer(string)
27
+ returns a textual description of the contents of the string argument
28
+ : check(filename)
29
+ checks the validity of entries in the colon separated database files
30
+ passed in as filename
31
+ : compile(filename)
32
+ compile the the colon separated list of database files passed in as
33
+ filename
34
+ : close()
35
+ closes the magic database and frees any memory allocated. if memory
36
+ is a concern, use this.
@@ -0,0 +1,177 @@
1
+ require 'filemagic.so'
2
+
3
+ class FileMagic
4
+
5
+ # Map abbreviated flag names to their values (:name => Constant).
6
+ MAGIC_FLAGS = [
7
+ :none, # No flags
8
+ :debug, # Turn on debugging
9
+ :symlink, # Follow symlinks
10
+ :compress, # Check inside compressed files
11
+ :devices, # Look at the contents of devices
12
+ :mime_type, # Return only the MIME type
13
+ :continue, # Return all matches
14
+ :check, # Print warnings to stderr
15
+ :preserve_atime, # Restore access time on exit
16
+ :raw, # Don't translate unprint chars
17
+ :error, # Handle ENOENT etc as real errors
18
+ :mime_encoding, # Return only the MIME encoding
19
+ :mime, # MAGIC_MIME_TYPE | MAGIC_MIME_ENCODING
20
+ :no_check_compress, # Don't check for compressed files
21
+ :no_check_tar, # Don't check for tar files
22
+ :no_check_soft, # Don't check magic entries
23
+ :no_check_apptype, # Don't check application type
24
+ :no_check_elf, # Don't check for elf details
25
+ :no_check_ascii, # Don't check for ascii files
26
+ :no_check_troff, # Don't check ascii/troff
27
+ :no_check_tokens, # Don't check ascii/tokens
28
+ :no_check_fortran # Don't check ascii/fortran
29
+ ].inject({}) { |flags, flag|
30
+ const = "MAGIC_#{flag.to_s.upcase}"
31
+ flags.update(flag => const_defined?(const) && const_get(const))
32
+ }
33
+
34
+ attr_reader :flags
35
+ attr_writer :simplified
36
+
37
+ @fm = Hash.new { |fm, flags|
38
+ fm.has_key?(key = flags.to_s) ? fm[key] : fm[key] = new(*flags)
39
+ }
40
+
41
+ class << self
42
+
43
+ # Provide a "magic singleton" ;-)
44
+ def fm(*flags)
45
+ @fm.delete(flags.to_s) if @fm[flags].closed?
46
+ @fm[flags]
47
+ end
48
+
49
+ # Clear our instance cache.
50
+ def clear!
51
+ @fm.each_value { |fm| fm.close }
52
+ @fm.clear
53
+ end
54
+
55
+ # Allow shorter names for flags; now also takes options.
56
+ def new(*flags)
57
+ warn "warning: FileMagic::new() does not take block; use FileMagic::open() instead" if block_given?
58
+
59
+ options = flags.last.is_a?(Hash) ? flags.pop : {}
60
+
61
+ fm = fm_new(build_flags(*flags))
62
+
63
+ options.each { |option, value|
64
+ if fm.respond_to?(method = "#{option}=")
65
+ fm.send(method, value)
66
+ else
67
+ raise ArgumentError, "illegal option: #{option.inspect}"
68
+ end
69
+ }
70
+
71
+ fm
72
+ end
73
+
74
+ # Just like #new, but takes an optional block, in which case #close is called at the end.
75
+ def open(*flags)
76
+ fm = new(*flags)
77
+
78
+ if block_given?
79
+ begin
80
+ yield fm
81
+ ensure
82
+ fm.close
83
+ end
84
+ end
85
+
86
+ fm
87
+ end
88
+
89
+ # Just a short-cut ;-)
90
+ def mime(*flags, &block)
91
+ open(:mime, *flags, &block)
92
+ end
93
+
94
+ # Build the actual flags from the named flags passed as arguments.
95
+ def build_flags(*flags)
96
+ _flags = *flags
97
+
98
+ unless _flags.is_a?(Integer)
99
+ _flags = MAGIC_NONE
100
+
101
+ flags.flatten.each { |flag|
102
+ if value = flag.is_a?(Integer) ? flag : MAGIC_FLAGS[flag.to_sym]
103
+ _flags |= value
104
+ else
105
+ raise ArgumentError, "#{value.nil? ? 'no such flag' : 'flag not available'}: #{flag}"
106
+ end
107
+ }
108
+ end
109
+
110
+ _flags
111
+ end
112
+
113
+ end
114
+
115
+ # The actual processing happens in #new.
116
+ def initialize(*flags)
117
+ fm_initialize(*flags)
118
+
119
+ @flags = *flags
120
+ @closed = false
121
+ end
122
+
123
+ def close
124
+ return if closed?
125
+
126
+ fm_close
127
+ @closed = true
128
+ end
129
+
130
+ # Optionally cut off additional information after mime-type.
131
+ def file(file, simplified = simplified?)
132
+ simplify_mime(fm_file(file), simplified)
133
+ end
134
+
135
+ # Optionally cut off additional information after mime-type.
136
+ def buffer(buffer, simplified = simplified?)
137
+ simplify_mime(fm_buffer(buffer), simplified)
138
+ end
139
+
140
+ def setflags(*flags)
141
+ previous_flags, @flags = @flags, self.class.build_flags(*flags)
142
+ fm_setflags(@flags)
143
+
144
+ previous_flags
145
+ end
146
+ alias_method :flags=, :setflags
147
+
148
+ def check(file = "\0")
149
+ fm_check(file)
150
+ end
151
+ alias_method :valid?, :check
152
+
153
+ def compile(file)
154
+ fm_compile(file)
155
+ end
156
+
157
+ def simplified?
158
+ @simplified
159
+ end
160
+
161
+ def closed?
162
+ @closed
163
+ end
164
+
165
+ def inspect
166
+ str = super
167
+ str.insert(-2, ' (closed)') if closed?
168
+ str
169
+ end
170
+
171
+ private
172
+
173
+ def simplify_mime(mime, simplified = true)
174
+ simplified ? mime[/([\w\/-]+)/, 1].downcase : mime
175
+ end
176
+
177
+ end
@@ -0,0 +1,95 @@
1
+ require 'filemagic'
2
+
3
+ module FileMagic::Ext
4
+
5
+ module ClassMethods
6
+
7
+ def file_type(file, *flags)
8
+ raise NotImplementedError, 'must be implemented by including class'
9
+ end
10
+
11
+ def file(file, *flags)
12
+ file_type(file, *flags)
13
+ end
14
+
15
+ def mime_type(file, *flags)
16
+ flags.unshift :mime
17
+ file_type(file, *flags)
18
+ end
19
+ alias_method :mime, :mime_type
20
+
21
+ def content_type(file, *flags)
22
+ flags << { :simplified => true }
23
+ mime_type(file, *flags)
24
+ end
25
+
26
+ end
27
+
28
+ module InstanceMethods
29
+
30
+ def file_type(*flags)
31
+ self.class.file_type(self, *flags)
32
+ end
33
+ alias_method :file, :file_type
34
+
35
+ def mime_type(*flags)
36
+ self.class.mime_type(self, *flags)
37
+ end
38
+ alias_method :mime, :mime_type
39
+
40
+ def content_type(*flags)
41
+ self.class.content_type(self, *flags)
42
+ end
43
+
44
+ end
45
+
46
+ end
47
+
48
+ class File
49
+
50
+ include FileMagic::Ext::InstanceMethods
51
+ extend FileMagic::Ext::ClassMethods
52
+
53
+ def self.file_type(file, *flags)
54
+ FileMagic.fm(*flags).file(file.respond_to?(:path) ? file.path : file)
55
+ rescue FileMagic::FileMagicError
56
+ nil
57
+ end
58
+
59
+ end
60
+
61
+ class String
62
+
63
+ include FileMagic::Ext::InstanceMethods
64
+ extend FileMagic::Ext::ClassMethods
65
+
66
+ def self.file_type(string, *flags)
67
+ FileMagic.fm(*flags).buffer(string)
68
+ rescue FileMagic::FileMagicError
69
+ nil
70
+ end
71
+
72
+ end
73
+
74
+ if $0 == __FILE__
75
+ f = __FILE__
76
+ p f
77
+
78
+ p File.file_type(f)
79
+ p File.mime_type(f)
80
+ p File.content_type(f)
81
+
82
+ f = File.new(f)
83
+ p f
84
+
85
+ p f.file_type
86
+ p f.mime_type
87
+ p f.content_type
88
+
89
+ s = '#! /usr/bin/ruby'
90
+ p s
91
+
92
+ p s.file_type
93
+ p s.mime_type
94
+ p s.content_type
95
+ end
@@ -0,0 +1,27 @@
1
+ class FileMagic
2
+
3
+ module Version
4
+
5
+ MAJOR = 0
6
+ MINOR = 2
7
+ TINY = 1
8
+
9
+ class << self
10
+
11
+ # Returns array representation.
12
+ def to_a
13
+ [MAJOR, MINOR, TINY]
14
+ end
15
+
16
+ # Short-cut for version string.
17
+ def to_s
18
+ to_a.join('.')
19
+ end
20
+
21
+ end
22
+
23
+ end
24
+
25
+ VERSION = Version.to_s
26
+
27
+ end
@@ -0,0 +1,124 @@
1
+ require 'test/unit'
2
+
3
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
4
+ require 'filemagic'
5
+
6
+ class TestFileMagic < Test::Unit::TestCase
7
+
8
+ def test_file
9
+ fm = FileMagic.new(FileMagic::MAGIC_NONE)
10
+
11
+ res = fm.file(path_to('pyfile'))
12
+ assert_equal('a python script text executable', res)
13
+
14
+ if File.symlink?(path_to('pylink'))
15
+ res = fm.file(path_to('pylink'))
16
+ assert_equal("symbolic link to `pyfile'", res)
17
+ end
18
+
19
+ fm.close
20
+ fm = FileMagic.new(FileMagic::MAGIC_SYMLINK)
21
+
22
+ res = fm.file(path_to('pylink'))
23
+ assert_equal('a python script text executable', res)
24
+
25
+ fm.close
26
+ fm = FileMagic.new(FileMagic::MAGIC_SYMLINK | FileMagic::MAGIC_MIME)
27
+
28
+ res = fm.file(path_to('pylink'))
29
+ assert_equal('text/plain; charset=us-ascii', res)
30
+
31
+ fm.close
32
+ fm = FileMagic.new(FileMagic::MAGIC_COMPRESS)
33
+
34
+ res = fm.file(path_to('pyfile-compressed.gz'))
35
+ assert_match(/^a python script text executable \(gzip compressed data, was "pyfile-compressed", from Unix/, res)
36
+
37
+ fm.close
38
+ end
39
+
40
+ def test_buffer
41
+ fm = FileMagic.new(FileMagic::MAGIC_NONE)
42
+ res = fm.buffer("#!/bin/sh\n")
43
+ fm.close
44
+ assert_match(/shell script text executable$/, res)
45
+ end
46
+
47
+ def test_check
48
+ fm = FileMagic.new(FileMagic::MAGIC_NONE)
49
+ res = fm.check(path_to('perl'))
50
+ fm.close
51
+ assert_equal(0, res)
52
+ end
53
+
54
+ def test_compile
55
+ assert(File.writable?('.'), "can't write to current directory")
56
+ fm = FileMagic.new(FileMagic::MAGIC_NONE)
57
+ res = fm.compile(path_to('perl'))
58
+ fm.close
59
+ assert_equal(0, res)
60
+ File.unlink(path_to('perl.mgc', '.'))
61
+ end
62
+
63
+ def test_block
64
+ block_fm = FileMagic.open(FileMagic::MAGIC_NONE) { |fm|
65
+ res = fm.file(path_to('pyfile'))
66
+ assert_equal('a python script text executable', res)
67
+ }
68
+ assert block_fm.closed?
69
+ end
70
+
71
+ def test_setflags
72
+ fm = FileMagic.new(FileMagic::MAGIC_NONE)
73
+ assert_equal(FileMagic::MAGIC_NONE, fm.flags)
74
+ fm.setflags(FileMagic::MAGIC_SYMLINK)
75
+ assert_equal(FileMagic::MAGIC_SYMLINK, fm.flags)
76
+ fm.close
77
+ end
78
+
79
+ def test_abbr
80
+ fm = FileMagic.new(:mime, :continue)
81
+ assert_equal(FileMagic::MAGIC_MIME | FileMagic::MAGIC_CONTINUE, fm.flags)
82
+ fm.setflags(:symlink)
83
+ assert_equal(FileMagic::MAGIC_SYMLINK, fm.flags)
84
+ fm.close
85
+ end
86
+
87
+ # tests adapted from mahoro:
88
+
89
+ def test_mahoro_file
90
+ fm = FileMagic.new
91
+ fm.flags = FileMagic::MAGIC_NONE
92
+ assert_equal('ASCII C program text', fm.file(path_to('mahoro.c')))
93
+ end
94
+
95
+ def test_mahoro_mime_file
96
+ fm = FileMagic.new
97
+ fm.flags = FileMagic::MAGIC_MIME
98
+ assert_equal('text/x-c; charset=us-ascii', fm.file(path_to('mahoro.c')))
99
+ end
100
+
101
+ def test_mahoro_buffer
102
+ fm = FileMagic.new
103
+ fm.flags = FileMagic::MAGIC_NONE
104
+ assert_equal('ASCII C program text', fm.buffer(File.read(path_to('mahoro.c'))))
105
+ end
106
+
107
+ def test_mahoro_mime_buffer
108
+ fm = FileMagic.new
109
+ fm.flags = FileMagic::MAGIC_MIME
110
+ assert_equal('text/x-c; charset=us-ascii', fm.buffer(File.read(path_to('mahoro.c'))))
111
+ end
112
+
113
+ def test_mahoro_valid
114
+ fm = FileMagic.new
115
+ assert(fm.valid?, 'Default database was not valid.')
116
+ end
117
+
118
+ # utility methods:
119
+
120
+ def path_to(file, dir = File.dirname(__FILE__))
121
+ File.join(dir, file)
122
+ end
123
+
124
+ end
@@ -0,0 +1,16 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ require 'filemagic'
3
+
4
+ warn "watch -n 1 'ps aux | grep [l]eaktest'"
5
+
6
+ def do_file(filename)
7
+ fm = FileMagic.new(0)
8
+ file = fm.file(filename)
9
+ fm.close
10
+ return file
11
+ end
12
+
13
+ loop do
14
+ puts do_file($0)
15
+ sleep 1
16
+ end
@@ -0,0 +1,187 @@
1
+ /*
2
+ * This file is Public Domain.
3
+ */
4
+
5
+ #include <ruby.h>
6
+ #include <magic.h>
7
+
8
+ struct MagicCookie
9
+ {
10
+ magic_t cookie;
11
+ };
12
+
13
+ static VALUE cMahoro;
14
+ static VALUE eMahoroError;
15
+
16
+ static void
17
+ mahoro_free(ptr)
18
+ struct MagicCookie *ptr;
19
+ {
20
+ magic_close(ptr->cookie);
21
+ free(ptr);
22
+ }
23
+
24
+ static VALUE
25
+ mahoro_allocate(klass)
26
+ VALUE klass;
27
+ {
28
+ return Data_Wrap_Struct(klass, 0, mahoro_free, 0);
29
+ }
30
+
31
+ static VALUE
32
+ mahoro_initialize(argc, argv, self)
33
+ int argc;
34
+ VALUE *argv, self;
35
+ {
36
+ int flags = MAGIC_NONE;
37
+ char *path = 0;
38
+ struct MagicCookie *ptr;
39
+ magic_t cookie;
40
+ VALUE vpath, vflags;
41
+
42
+ switch(rb_scan_args(argc, argv, "02", &vflags, &vpath)) {
43
+ case 2:
44
+ if(!NIL_P(vpath)) {
45
+ path = StringValuePtr(vpath);
46
+ }
47
+ /* fallthrough */
48
+ case 1:
49
+ flags = FIX2INT(vflags);
50
+ break;
51
+ }
52
+
53
+ if(!(cookie = magic_open(flags))) {
54
+ rb_raise(eMahoroError, "failed to initialize magic cookie");
55
+ }
56
+
57
+ if(magic_load(cookie, path)) {
58
+ rb_raise(eMahoroError, "failed to load database: %s",
59
+ magic_error(cookie));
60
+ }
61
+
62
+ ptr = ALLOC(struct MagicCookie);
63
+ ptr->cookie = cookie;
64
+ DATA_PTR(self) = ptr;
65
+
66
+ return self;
67
+ }
68
+
69
+ static VALUE
70
+ mahoro_file(self, path)
71
+ VALUE self, path;
72
+ {
73
+ const char *msg;
74
+ magic_t cookie = ((struct MagicCookie *) DATA_PTR(self))->cookie;
75
+
76
+ if(!(msg = magic_file(cookie, StringValuePtr(path)))) {
77
+ rb_raise(eMahoroError, "failed lookup: %s", magic_error(cookie));
78
+ }
79
+
80
+ return rb_str_new2(msg);
81
+ }
82
+
83
+ static VALUE
84
+ mahoro_buffer(self, input)
85
+ VALUE self, input;
86
+ {
87
+ const char *msg;
88
+ magic_t cookie = ((struct MagicCookie *) DATA_PTR(self))->cookie;
89
+
90
+ if(!(msg = magic_buffer(cookie, StringValuePtr(input),
91
+ RSTRING(StringValue(input))->len))) {
92
+ rb_raise(eMahoroError, "failed lookup: %s", magic_error(cookie));
93
+ }
94
+
95
+ return rb_str_new2(msg);
96
+ }
97
+
98
+ static VALUE
99
+ mahoro_set_flags(self, flags)
100
+ VALUE self, flags;
101
+ {
102
+ magic_t cookie = ((struct MagicCookie *) DATA_PTR(self))->cookie;
103
+
104
+ return INT2FIX(magic_setflags(cookie, FIX2INT(flags)));
105
+ }
106
+
107
+ static VALUE
108
+ mahoro_check(argc, argv, self)
109
+ int argc;
110
+ VALUE *argv, self;
111
+ {
112
+ char *path = 0;
113
+ VALUE vpath;
114
+ magic_t cookie = ((struct MagicCookie *) DATA_PTR(self))->cookie;
115
+
116
+ switch(rb_scan_args(argc, argv, "01", &vpath)) {
117
+ case 1:
118
+ if(!NIL_P(vpath)) {
119
+ path = StringValuePtr(vpath);
120
+ }
121
+ break;
122
+ }
123
+
124
+ if(!magic_check(cookie, path)) {
125
+ return Qtrue;
126
+ } else {
127
+ return Qfalse;
128
+ }
129
+ }
130
+
131
+ static VALUE
132
+ mahoro_compile(klass, path)
133
+ VALUE klass, path;
134
+ {
135
+ magic_t cookie = magic_open(MAGIC_NONE);
136
+
137
+ if(magic_compile(cookie, StringValuePtr(path))) {
138
+ rb_raise(eMahoroError, "failed compile: %s", magic_error(cookie));
139
+ }
140
+
141
+ magic_close(cookie);
142
+
143
+ return Qtrue;
144
+ }
145
+
146
+ static VALUE
147
+ mahoro_load(self, path)
148
+ VALUE self, path;
149
+ {
150
+ magic_t cookie = ((struct MagicCookie *) DATA_PTR(self))->cookie;
151
+
152
+ if(magic_load(cookie, StringValuePtr(path))) {
153
+ rb_raise(eMahoroError, "failed load: %s", magic_error(cookie));
154
+ }
155
+
156
+ return self;
157
+ }
158
+
159
+ void Init_mahoro(void)
160
+ {
161
+ cMahoro = rb_define_class("Mahoro", rb_cObject);
162
+ eMahoroError = rb_define_class_under(cMahoro, "Error", rb_eStandardError);
163
+
164
+ rb_const_set(cMahoro, rb_intern("NONE"), INT2FIX(MAGIC_NONE));
165
+ rb_const_set(cMahoro, rb_intern("DEBUG"), INT2FIX(MAGIC_DEBUG));
166
+ rb_const_set(cMahoro, rb_intern("SYMLINK"), INT2FIX(MAGIC_SYMLINK));
167
+ rb_const_set(cMahoro, rb_intern("COMPRESS"), INT2FIX(MAGIC_COMPRESS));
168
+ rb_const_set(cMahoro, rb_intern("DEVICES"), INT2FIX(MAGIC_DEVICES));
169
+ rb_const_set(cMahoro, rb_intern("MIME"), INT2FIX(MAGIC_MIME));
170
+ rb_const_set(cMahoro, rb_intern("CONTINUE"), INT2FIX(MAGIC_CONTINUE));
171
+ rb_const_set(cMahoro, rb_intern("CHECK"), INT2FIX(MAGIC_CHECK));
172
+ rb_const_set(cMahoro, rb_intern("PRESERVE_ATIME"),
173
+ INT2FIX(MAGIC_PRESERVE_ATIME));
174
+ rb_const_set(cMahoro, rb_intern("RAW"), INT2FIX(MAGIC_RAW));
175
+ rb_const_set(cMahoro, rb_intern("ERROR"), INT2FIX(MAGIC_ERROR));
176
+
177
+ rb_define_alloc_func(cMahoro, mahoro_allocate);
178
+ rb_define_method(cMahoro, "initialize", mahoro_initialize, -1);
179
+ rb_define_method(cMahoro, "file", mahoro_file, 1);
180
+ rb_define_method(cMahoro, "buffer", mahoro_buffer, 1);
181
+ rb_define_method(cMahoro, "flags=", mahoro_set_flags, 1);
182
+ rb_define_method(cMahoro, "valid?", mahoro_check, -1);
183
+ rb_define_singleton_method(cMahoro, "compile", mahoro_compile, 1);
184
+ rb_define_method(cMahoro, "load", mahoro_load, 1);
185
+ }
186
+
187
+ /* arch-tag: mahoro */
@@ -0,0 +1,19 @@
1
+
2
+ #------------------------------------------------------------------------------
3
+ # perl: file(1) magic for Larry Wall's perl language.
4
+ #
5
+ # The ``eval'' line recognizes an outrageously clever hack for USG systems.
6
+ # Keith Waclena <keith@cerberus.uchicago.edu>
7
+ # Send additions to <perl5-porters@perl.org>
8
+ 0 string/b #!\ /bin/perl perl script text executable
9
+ 0 string eval\ "exec\ /bin/perl perl script text
10
+ 0 string/b #!\ /usr/bin/perl perl script text executable
11
+ 0 string eval\ "exec\ /usr/bin/perl perl script text
12
+ 0 string/b #!\ /usr/local/bin/perl perl script text
13
+ 0 string eval\ "exec\ /usr/local/bin/perl perl script text executable
14
+ 0 string eval\ '(exit\ $?0)'\ &&\ eval\ 'exec perl script text
15
+
16
+ # a couple more, by me
17
+ # XXX: christos matches
18
+ #0 regex package Perl5 module source text (via regex)
19
+ 0 string package Perl5 module source text
@@ -0,0 +1 @@
1
+ """
Binary file
@@ -0,0 +1 @@
1
+ """
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-filemagic
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
+ platform: ruby
6
+ authors:
7
+ - Travis Whitton
8
+ - Jens Wille
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2008-09-18 00:00:00 +02:00
14
+ default_executable:
15
+ dependencies: []
16
+
17
+ description: Ruby bindings to the magic(4) library
18
+ email:
19
+ - tinymountain@gmail.com
20
+ - jens.wille@uni-koeln.de
21
+ executables: []
22
+
23
+ extensions:
24
+ - ext/extconf.rb
25
+ extra_rdoc_files:
26
+ - README
27
+ files:
28
+ - lib/filemagic/ext.rb
29
+ - lib/filemagic/version.rb
30
+ - lib/filemagic.rb
31
+ - ext/filemagic.c
32
+ - test/pyfile
33
+ - test/pyfile-compressed.gz
34
+ - test/perl
35
+ - test/leaktest.rb
36
+ - test/mahoro.c
37
+ - test/filemagic_test.rb
38
+ - test/pylink
39
+ - README
40
+ - CHANGELOG
41
+ - TODO
42
+ - Rakefile
43
+ - info/filemagic.rd
44
+ - info/example.rb
45
+ has_rdoc: true
46
+ homepage: http://ruby-filemagic.rubyforge.org/
47
+ post_install_message:
48
+ rdoc_options:
49
+ - --line-numbers
50
+ - --main
51
+ - README
52
+ - --all
53
+ - --inline-source
54
+ - --title
55
+ - ruby-filemagic Application documentation
56
+ - --charset
57
+ - UTF-8
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: "0"
65
+ version:
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: "0"
71
+ version:
72
+ requirements: []
73
+
74
+ rubyforge_project: ruby-filemagic
75
+ rubygems_version: 1.2.0
76
+ signing_key:
77
+ specification_version: 2
78
+ summary: Ruby bindings to the magic(4) library
79
+ test_files: []
80
+