ruby-magic 0.3.2 → 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -10,11 +10,8 @@ extern "C" {
10
10
 
11
11
  #define MAGIC_SYNCHRONIZED(f, d) magic_lock(object, (f), (d))
12
12
 
13
- #define MAGIC_OBJECT(o) \
14
- Data_Get_Struct(object, magic_object_t, (o))
15
-
16
- #define MAGIC_COOKIE(o, c) \
17
- ((c) = MAGIC_OBJECT((o))->cookie)
13
+ #define MAGIC_OBJECT(o, t) \
14
+ TypedData_Get_Struct((o), rb_mgc_object_t, &rb_mgc_type, (t))
18
15
 
19
16
  #define MAGIC_CLOSED_P(o) RTEST(rb_mgc_close_p((o)))
20
17
  #define MAGIC_LOADED_P(o) RTEST(rb_mgc_load_p((o)))
@@ -25,64 +22,66 @@ extern "C" {
25
22
  rb_mgc_warning |= BIT(i); \
26
23
  rb_warn(__VA_ARGS__); \
27
24
  } \
28
- } while(0)
25
+ } while (0)
26
+
27
+ #define MAGIC_ERRORS(t) ruby_magic_errors[(t)]
29
28
 
30
29
  #define MAGIC_ARGUMENT_TYPE_ERROR(o, ...) \
31
- rb_raise(rb_eTypeError, error(E_ARGUMENT_TYPE_INVALID), CLASS_NAME((o)), __VA_ARGS__)
30
+ rb_raise(rb_eTypeError, MAGIC_ERRORS(E_ARGUMENT_TYPE_INVALID), CLASS_NAME((o)), __VA_ARGS__)
32
31
 
33
32
  #define MAGIC_GENERIC_ERROR(k, e, m) \
34
- rb_exc_raise(magic_generic_error((k), (e), error(m)))
33
+ rb_exc_raise(magic_generic_error((k), (e), MAGIC_ERRORS(m)))
35
34
 
36
35
  #define MAGIC_LIBRARY_ERROR(c) \
37
- rb_exc_raise(magic_library_error(rb_mgc_eMagicError, (c)))
36
+ rb_exc_raise(magic_library_error(rb_mgc_eMagicError, (c)->cookie))
38
37
 
39
38
  #define MAGIC_CHECK_INTEGER_TYPE(o) magic_check_type((o), T_FIXNUM)
40
39
  #define MAGIC_CHECK_STRING_TYPE(o) magic_check_type((o), T_STRING)
41
40
 
42
- #define MAGIC_CHECK_ARGUMENT_MISSING(t, o) \
43
- do { \
44
- if ((t) < (o)) \
45
- rb_raise(rb_eArgError, error(E_ARGUMENT_MISSING), (t), (o)); \
46
- } while(0)
47
-
48
- #define MAGIC_CHECK_ARRAY_EMPTY(o) \
49
- do { \
50
- if (RARRAY_EMPTY_P(o)) \
51
- rb_raise(rb_eArgError, "%s", error(E_ARGUMENT_TYPE_ARRAY_EMPTY)); \
52
- } while(0)
53
-
54
41
  #define MAGIC_CHECK_ARRAY_OF_STRINGS(o) \
55
42
  magic_check_type_array_of_strings((o))
56
43
 
44
+ #define MAGIC_CHECK_ARGUMENT_MISSING(t, o) \
45
+ do { \
46
+ if ((t) < (o)) \
47
+ rb_raise(rb_eArgError, MAGIC_ERRORS(E_ARGUMENT_MISSING), (t), (o)); \
48
+ } while (0)
49
+
50
+ #define MAGIC_CHECK_ARRAY_EMPTY(o) \
51
+ do { \
52
+ if (RARRAY_EMPTY_P(o)) \
53
+ rb_raise(rb_eArgError, "%s", MAGIC_ERRORS(E_ARGUMENT_TYPE_ARRAY_EMPTY)); \
54
+ } while (0)
55
+
56
+
57
57
  #define MAGIC_CHECK_OPEN(o) \
58
58
  do { \
59
59
  if (MAGIC_CLOSED_P(o)) \
60
60
  MAGIC_GENERIC_ERROR(rb_mgc_eLibraryError, EFAULT, \
61
61
  E_MAGIC_LIBRARY_CLOSED); \
62
- } while(0)
62
+ } while (0)
63
63
 
64
64
  #define MAGIC_CHECK_LOADED(o) \
65
65
  do { \
66
66
  if (!MAGIC_LOADED_P(o)) \
67
67
  MAGIC_GENERIC_ERROR(rb_mgc_eMagicError, EFAULT, \
68
68
  E_MAGIC_LIBRARY_NOT_LOADED); \
69
- } while(0)
69
+ } while (0)
70
70
 
71
71
  #define MAGIC_STRINGIFY(s) #s
72
72
 
73
73
  #define MAGIC_DEFINE_FLAG(c) \
74
- rb_define_const(rb_cMagic, MAGIC_STRINGIFY(c), INT2NUM(MAGIC_##c));
74
+ rb_define_const(rb_cMagic, MAGIC_STRINGIFY(c), INT2NUM(MAGIC_##c))
75
75
 
76
76
  #define MAGIC_DEFINE_PARAMETER(c) \
77
- rb_define_const(rb_cMagic, MAGIC_STRINGIFY(PARAM_##c), INT2NUM(MAGIC_PARAM_##c));
78
-
79
- #define error(t) errors[(t)]
77
+ rb_define_const(rb_cMagic, MAGIC_STRINGIFY(PARAM_##c), INT2NUM(MAGIC_PARAM_##c))
80
78
 
81
- enum error {
79
+ enum ruby_magic_error {
82
80
  E_UNKNOWN = 0,
83
81
  E_NOT_ENOUGH_MEMORY,
84
82
  E_ARGUMENT_MISSING,
85
83
  E_ARGUMENT_TYPE_INVALID,
84
+ E_ARGUMENT_TYPE_UNKNOWN,
86
85
  E_ARGUMENT_TYPE_ARRAY_EMPTY,
87
86
  E_ARGUMENT_TYPE_ARRAY_STRINGS,
88
87
  E_MAGIC_LIBRARY_INITIALIZE,
@@ -94,53 +93,53 @@ enum error {
94
93
  E_FLAG_INVALID_TYPE
95
94
  };
96
95
 
97
- typedef struct parameter {
98
- size_t value;
96
+ struct parameter {
99
97
  int tag;
100
- } parameter_t;
98
+ size_t value;
99
+ };
101
100
 
102
- typedef union file {
101
+ union file {
103
102
  const char *path;
104
103
  int fd;
105
- } file_t;
104
+ };
106
105
 
107
- typedef struct buffers {
106
+ struct buffers {
108
107
  size_t count;
109
108
  size_t *sizes;
110
109
  void **pointers;
111
- } buffers_t;
110
+ };
112
111
 
113
112
  typedef struct magic_object {
114
113
  magic_t cookie;
115
114
  VALUE mutex;
116
115
  unsigned int database_loaded:1;
117
116
  unsigned int stop_on_errors:1;
118
- } magic_object_t;
117
+ } rb_mgc_object_t;
119
118
 
120
119
  typedef struct magic_arguments {
120
+ rb_mgc_object_t *magic_object;
121
121
  union {
122
- file_t file;
123
- parameter_t parameter;
124
- buffers_t buffers;
125
- } type;
126
- magic_t cookie;
122
+ struct parameter parameter;
123
+ union file file;
124
+ struct buffers buffers;
125
+ };
127
126
  const char *result;
128
- int flags;
129
127
  int status;
130
- unsigned int stop_on_errors:1;
131
- } magic_arguments_t;
128
+ int flags;
129
+ } rb_mgc_arguments_t;
132
130
 
133
- typedef struct magic_exception {
131
+ typedef struct magic_error {
134
132
  const char *magic_error;
135
133
  VALUE klass;
136
134
  int magic_errno;
137
- } magic_exception_t;
135
+ } rb_mgc_error_t;
138
136
 
139
- static const char *errors[] = {
137
+ static const char * const ruby_magic_errors[] = {
140
138
  [E_UNKNOWN] = "an unknown error has occurred",
141
139
  [E_NOT_ENOUGH_MEMORY] = "cannot allocate memory",
142
140
  [E_ARGUMENT_MISSING] = "wrong number of arguments (given %d, expected %d)",
143
141
  [E_ARGUMENT_TYPE_INVALID] = "wrong argument type %s (expected %s)",
142
+ [E_ARGUMENT_TYPE_UNKNOWN] = "unknown type 0x%x (0x%x given)",
144
143
  [E_ARGUMENT_TYPE_ARRAY_EMPTY] = "arguments list cannot be empty (expected array of String)",
145
144
  [E_ARGUMENT_TYPE_ARRAY_STRINGS] = "wrong argument type %s in arguments list (expected String)",
146
145
  [E_MAGIC_LIBRARY_INITIALIZE] = "failed to initialize Magic library",
@@ -153,38 +152,158 @@ static const char *errors[] = {
153
152
  NULL
154
153
  };
155
154
 
155
+ #if defined(MAGIC_CUSTOM_CHECK_TYPE)
156
+ static const char * const magic_ruby_types[] = {
157
+ "", /* Not an object */
158
+ [T_OBJECT] = "Object",
159
+ [T_CLASS] = "Class",
160
+ [T_MODULE] = "Module",
161
+ [T_FLOAT] = "Float",
162
+ [T_STRING] = "String",
163
+ [T_REGEXP] = "Regexp",
164
+ [T_ARRAY] = "Array",
165
+ [T_HASH] = "Hash",
166
+ [T_STRUCT] = "Struct",
167
+ [T_BIGNUM] = "Integer",
168
+ [T_FILE] = "File",
169
+ "", /* Internal use */
170
+ [T_MATCH] = "MatchData",
171
+ [T_COMPLEX] = "Complex",
172
+ [T_RATIONAL] = "Rational",
173
+ "", /* Internal use */
174
+ [T_NIL] = "nil",
175
+ [T_TRUE] = "true",
176
+ [T_FALSE] = "false",
177
+ [T_SYMBOL] = "Symbol",
178
+ [T_FIXNUM] = "Integer",
179
+ "", /* Internal use */
180
+ NULL
181
+ };
182
+
183
+ static const char *
184
+ magic_ruby_type_name(int type)
185
+ {
186
+ const char *name;
187
+
188
+ if (type >= ARRAY_SIZE(magic_ruby_types))
189
+ return NULL;
190
+
191
+ name = magic_ruby_types[type];
192
+ if (name)
193
+ return name;
194
+
195
+ return NULL;
196
+ }
197
+
198
+ static const char *
199
+ magic_ruby_class_name(VALUE object)
200
+ {
201
+ const char *name = NULL;
202
+
203
+ if (NIL_P(object))
204
+ name = "nil";
205
+ else if (RB_TYPE_P(object, T_TRUE))
206
+ name = "true";
207
+ else if (RB_TYPE_P(object, T_FALSE))
208
+ name = "false";
209
+ else
210
+ name = CLASS_NAME(object);
211
+
212
+ return name;
213
+ }
214
+
215
+ void
216
+ magic_check_ruby_type(VALUE object, int type)
217
+ {
218
+ const char *name;
219
+ int object_type = TYPE(object);
220
+
221
+ if (object == Qundef)
222
+ rb_bug("invalid type leaked to the Ruby space");
223
+
224
+ if (object_type > T_MASK || object_type == T_DATA)
225
+ goto error;
226
+
227
+ if (object_type == type)
228
+ return;
229
+
230
+ name = magic_ruby_type_name(type);
231
+ if (name)
232
+ rb_raise(rb_eTypeError,
233
+ MAGIC_ERRORS(E_ARGUMENT_TYPE_INVALID),
234
+ magic_ruby_class_name(object),
235
+ name);
236
+ error:
237
+ rb_raise(rb_eTypeError,
238
+ MAGIC_ERRORS(E_ARGUMENT_TYPE_UNKNOWN),
239
+ object_type,
240
+ type);
241
+ }
242
+ #endif /* MAGIC_CUSTOM_CHECK_TYPE */
243
+
244
+ static inline VALUE
245
+ magic_strip(VALUE v)
246
+ {
247
+ return (ARRAY_P(v) || STRING_P(v)) ?
248
+ rb_funcall(v, rb_intern("strip"), 0) :
249
+ Qnil;
250
+ }
251
+
156
252
  static inline VALUE
157
253
  magic_shift(VALUE v)
158
254
  {
159
- return ARRAY_P(v) ? \
160
- rb_funcall(v, rb_intern("shift"), 0) : \
255
+ return ARRAY_P(v) ?
256
+ rb_funcall(v, rb_intern("shift"), 0) :
161
257
  Qnil;
162
258
  }
163
259
 
164
260
  static inline VALUE
165
261
  magic_split(VALUE a, VALUE b)
166
262
  {
167
- return (STRING_P(a) && STRING_P(b)) ? \
168
- rb_funcall(a, rb_intern("split"), 1, b) : \
263
+ return (STRING_P(a) && STRING_P(b)) ?
264
+ rb_funcall(a, rb_intern("split"), 1, b) :
169
265
  Qnil;
170
266
  }
171
267
 
172
268
  static inline VALUE
173
269
  magic_join(VALUE a, VALUE b)
174
270
  {
175
- return (ARRAY_P(a) && STRING_P(b)) ? \
176
- rb_funcall(a, rb_intern("join"), 1, b) : \
271
+ return (ARRAY_P(a) && STRING_P(b)) ?
272
+ rb_funcall(a, rb_intern("join"), 1, b) :
177
273
  Qnil;
178
274
  }
179
275
 
180
276
  static inline VALUE
181
277
  magic_flatten(VALUE v)
182
278
  {
183
- return ARRAY_P(v) ? \
184
- rb_funcall(v, rb_intern("flatten"), 0) : \
279
+ return ARRAY_P(v) ?
280
+ rb_funcall(v, rb_intern("flatten"), 0) :
185
281
  Qnil;
186
282
  }
187
283
 
284
+ static inline VALUE
285
+ magic_strip_array(VALUE value) {
286
+ VALUE entry;
287
+ VALUE array = rb_ary_new();
288
+
289
+ for (int i = 0; i < RARRAY_LEN(value); i++) {
290
+ entry = rb_ary_entry(value, i);
291
+ if (NIL_P(entry))
292
+ continue;
293
+
294
+ if (STRING_P(entry)) {
295
+ if (RSTRING_EMPTY_P(entry))
296
+ continue;
297
+
298
+ entry = magic_strip(entry);
299
+ }
300
+
301
+ rb_ary_push(array, entry);
302
+ }
303
+
304
+ return array;
305
+ }
306
+
188
307
  static int
189
308
  magic_fileno(VALUE object)
190
309
  {
@@ -200,7 +319,9 @@ magic_fileno(VALUE object)
200
319
  object = rb_convert_type(object, T_FILE, "IO", "to_io");
201
320
 
202
321
  GetOpenFile(object, io);
203
- if ((fd = FPTR_TO_FD(io)) < 0)
322
+
323
+ fd = FPTR_TO_FD(io);
324
+ if (fd < 0)
204
325
  rb_raise(rb_eIOError, "closed stream");
205
326
 
206
327
  return fd;
@@ -227,33 +348,66 @@ magic_path(VALUE object)
227
348
  static inline void
228
349
  magic_check_type(VALUE object, RVALUE_TYPE type)
229
350
  {
230
- VALUE boolean = Qundef;
351
+ VALUE boolean;
231
352
 
232
353
  boolean = rb_obj_is_kind_of(object, T_INTEGER);
233
354
  if (type == T_FIXNUM && !RVAL2CBOOL(boolean))
234
355
  MAGIC_ARGUMENT_TYPE_ERROR(object, rb_class2name(T_INTEGER));
235
356
 
236
- Check_Type(object, type);
357
+ MAGIC_CHECK_RUBY_TYPE(object, type);
237
358
  }
238
359
 
239
360
  static inline void
240
361
  magic_check_type_array_of_strings(VALUE object)
241
362
  {
242
- VALUE value = Qundef;
363
+ VALUE value;
243
364
 
244
365
  for (int i = 0; i < RARRAY_LEN(object); i++) {
245
366
  value = RARRAY_AREF(object, (long)i);
246
367
  if (NIL_P(value) || !STRING_P(value))
247
368
  rb_raise(rb_eTypeError,
248
- error(E_ARGUMENT_TYPE_ARRAY_STRINGS),
369
+ MAGIC_ERRORS(E_ARGUMENT_TYPE_ARRAY_STRINGS),
249
370
  CLASS_NAME(value));
250
371
  }
251
372
  }
252
373
 
374
+ void Init_magic(void);
375
+
376
+ VALUE rb_mgc_get_do_not_auto_load_global(VALUE object);
377
+ VALUE rb_mgc_set_do_not_auto_load_global(VALUE object, VALUE value);
378
+ VALUE rb_mgc_get_do_not_stop_on_error_global(VALUE object);
379
+ VALUE rb_mgc_set_do_not_stop_on_error_global(VALUE object, VALUE value);
380
+
381
+ VALUE rb_mgc_initialize(VALUE object, VALUE arguments);
382
+
383
+ VALUE rb_mgc_get_do_not_stop_on_error(VALUE object);
384
+ VALUE rb_mgc_set_do_not_stop_on_error(VALUE object, VALUE value);
385
+
386
+ VALUE rb_mgc_open_p(VALUE object);
387
+ VALUE rb_mgc_close(VALUE object);
253
388
  VALUE rb_mgc_close_p(VALUE object);
389
+
390
+ VALUE rb_mgc_get_paths(VALUE object);
391
+
392
+ VALUE rb_mgc_get_parameter(VALUE object, VALUE tag);
393
+ VALUE rb_mgc_set_parameter(VALUE object, VALUE tag, VALUE value);
394
+
395
+ VALUE rb_mgc_get_flags(VALUE object);
396
+ VALUE rb_mgc_set_flags(VALUE object, VALUE value);
397
+
254
398
  VALUE rb_mgc_load(VALUE object, VALUE arguments);
399
+ VALUE rb_mgc_load_buffers(VALUE object, VALUE arguments);
400
+ VALUE rb_mgc_load_p(VALUE object);
401
+
402
+ VALUE rb_mgc_compile(VALUE object, VALUE arguments);
403
+ VALUE rb_mgc_check(VALUE object, VALUE arguments);
404
+
405
+ VALUE rb_mgc_file(VALUE object, VALUE value);
406
+ VALUE rb_mgc_buffer(VALUE object, VALUE value);
255
407
  VALUE rb_mgc_descriptor(VALUE object, VALUE value);
256
408
 
409
+ VALUE rb_mgc_version(VALUE object);
410
+
257
411
  #if defined(__cplusplus)
258
412
  }
259
413
  #endif
data/lib/magic/version.rb CHANGED
@@ -4,7 +4,7 @@ class Magic
4
4
  #
5
5
  # Current version of _Magic_.
6
6
  #
7
- VERSION = '0.3.2'.freeze
7
+ VERSION = '0.5.3'.freeze
8
8
 
9
9
  class << self
10
10
  #
data/lib/magic.rb CHANGED
@@ -1,6 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'magic/magic'
3
+ begin
4
+ ::RUBY_VERSION =~ /(\d+\.\d+)/
5
+ require_relative "magic/#{Regexp.last_match(1)}/magic"
6
+ rescue LoadError
7
+ # use "require" instead of "require_relative" because non-native gems will place C extension files
8
+ # in Gem::BasicSpecification#extension_dir after compilation (during normal installation), which
9
+ # is in $LOAD_PATH but not necessarily relative to this file (see #21 and nokogiri#2300)
10
+ require 'magic/magic'
11
+ end
12
+
4
13
  require_relative 'magic/version'
5
14
  require_relative 'magic/core/file'
6
15
  require_relative 'magic/core/string'
@@ -95,6 +104,8 @@ class Magic
95
104
  open(Magic::MIME, &block)
96
105
  end
97
106
 
107
+ alias_method :mime_type, :mime
108
+
98
109
  #
99
110
  # call-seq:
100
111
  # Magic.type -> self
@@ -175,6 +186,13 @@ class Magic
175
186
  end
176
187
 
177
188
  alias_method :fd, :descriptor
189
+
190
+ private
191
+
192
+ def default_paths
193
+ paths = Dir.glob(File.expand_path(File.join(File.dirname(__FILE__), "../ext/magic/share/*.mgc")))
194
+ paths.empty? ? nil : paths
195
+ end
178
196
  end
179
197
 
180
198
  private
metadata CHANGED
@@ -1,15 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-magic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.5.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Krzysztof Wilczyński
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
- cert_chain:
11
- - kwilczynski-public.pem
12
- date: 2021-04-03 00:00:00.000000000 Z
10
+ cert_chain: []
11
+ date: 2021-12-22 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: mini_portile2
@@ -17,14 +16,14 @@ dependencies:
17
16
  requirements:
18
17
  - - "~>"
19
18
  - !ruby/object:Gem::Version
20
- version: 2.5.0
19
+ version: '2.6'
21
20
  type: :runtime
22
21
  prerelease: false
23
22
  version_requirements: !ruby/object:Gem::Requirement
24
23
  requirements:
25
24
  - - "~>"
26
25
  - !ruby/object:Gem::Version
27
- version: 2.5.0
26
+ version: '2.6'
28
27
  description: |
29
28
  File Magic in Ruby.
30
29
 
@@ -42,6 +41,7 @@ files:
42
41
  - LICENSE
43
42
  - NOTICE
44
43
  - README.md
44
+ - dependencies.yml
45
45
  - ext/magic/common.h
46
46
  - ext/magic/extconf.rb
47
47
  - ext/magic/functions.c
@@ -64,7 +64,7 @@ metadata:
64
64
  wiki_uri: https://github.com/kwilczynski/ruby-magic/wiki
65
65
  post_install_message: 'Thank you for installing!
66
66
 
67
- '
67
+ '
68
68
  rdoc_options: []
69
69
  require_paths:
70
70
  - lib
@@ -80,8 +80,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
80
80
  - !ruby/object:Gem::Version
81
81
  version: '0'
82
82
  requirements: []
83
- rubygems_version: 3.1.4
84
- signing_key:
83
+ rubygems_version: 3.2.28
84
+ signing_key:
85
85
  specification_version: 4
86
86
  summary: File Magic in Ruby
87
87
  test_files: []