libmagic_rb 0.1.0.pre.alpha

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ba9f8adbdc49d3228f29e2678aef99bdd015a2134a57f9dbeb630b2e81118797
4
+ data.tar.gz: b13bab746fa7c6daf2baa5dd7e17531a17588c27c9accf6229e92de7d412d4b4
5
+ SHA512:
6
+ metadata.gz: 6ac39fbc412c0d45774b78d6d2ef0a44f7b9632b6dc58b4afa140e04868a8abd0caa279cd53c73d9648a4256b2e95ca656d4cd24fa96e3d127e1ee58ec300bb2
7
+ data.tar.gz: 48e98649e0e24ea017f0234e5771ddf63303316815c2ee59eec9aef6ee659ca563766ee9ca708a2fa9d483b4f09051a321744bae7ebec3ddc9e58c43fdc3f299
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2021 Cybergizer
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,188 @@
1
+ # LibmagicRb
2
+ 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
+ It uses native extensions and it's quite performant.
4
+
5
+ ## Pre-Installation
6
+ On Linux, you need to install libmagic.
7
+
8
+ ##### Arch
9
+
10
+ ```
11
+ # pacman -S file gcc make
12
+ ```
13
+
14
+ #### Debian / Ubuntu / Linux Mint / Kali / ParrotOS / RaspberryPi OS
15
+
16
+ ```
17
+ # apt install libmagic-dev ruby-dev gcc make
18
+ ```
19
+
20
+ #### Fedora
21
+
22
+ ```
23
+ # yum install file-devel ruby-devel gcc make
24
+ ```
25
+
26
+ #### OpenSUSE
27
+
28
+ ```
29
+ zypper in ruby ruby-devel file-devel gcc make
30
+ ```
31
+
32
+ Mac is currently not supported but may support in the future.
33
+
34
+ ## Installation
35
+
36
+ Add this line to your application's Gemfile:
37
+
38
+ ```ruby
39
+ gem 'libmagic_rb'
40
+ ```
41
+
42
+ And then execute:
43
+
44
+ ```
45
+ $ bundle install
46
+ ```
47
+
48
+ Or install it yourself as:
49
+
50
+ ```
51
+ $ gem install libmagic_rb
52
+ ```
53
+
54
+ ## Usage
55
+ The target of this gem is to add mime-type checking easily.
56
+
57
+ Using the LibmagicRb class we can check the mime type, EXIF data and other information of a file.
58
+
59
+ To check a file, you need to pass a hash argument to the FilemagicRb.new():
60
+
61
+ 1. db: Path to the Database (String)
62
+ 2. file: A file to check (String)
63
+ 3. mode: Modes of the file (Integer) (Optional, defaults to `LibmagicRb::MAGIC_MIME | LibmagicRb::MAGIC_CHECK | LibmagicRb::MAGIC_SYMLINK`)
64
+
65
+ ### Example 1:
66
+
67
+ ```
68
+ require 'libmagic_rb'
69
+
70
+ cookie = LibmagicRb.new(
71
+ file: '/usr/share/backgrounds/myimage.webp',
72
+ mode: LibmagicRb::MAGIC_MIME | LibmagicRb::MAGIC_CHECK | LibmagicRb::MAGIC_SYMLINK
73
+ )
74
+
75
+ p cookie # => #<LibmagicRb:0x000055cf96d8f868 @db="/home/sourav/.gem/ruby/3.0.0/gems/libmagic_rb-0.1.0/data/magic.mgc", @file="/usr/share/backgrounds/myimage.webp", @mode=1106, @closed=false>
76
+
77
+ # In case The file path needs to be changed
78
+ cookie.file = '/usr/share/backgrounds/vienna-5164602.jpg'
79
+
80
+ p cookie.file # => "/usr/share/backgrounds/vienna-5164602.jpg"
81
+ p cookie.db # => nil
82
+
83
+ cookie.check() # => image/jpeg; charset=binary
84
+ cookie.close() # => #<LibmagicRb:0x000055fa77699818 @closed=true, @db="/home/sourav/.gem/ruby/3.0.0/gems/libmagic_rb-0.1.0/data/magic.mgc", @file="/usr/share/backgrounds/vienna-5164602.jpg", @mode=1106>
85
+ cookie.closed?() # => true
86
+ ```
87
+
88
+ When the `db:` key is `nil`, it will use NULL as the database file - which gets the database automatically from the system.
89
+ You can omit `db: nil` as well for a nil value.
90
+
91
+ ### Example 2:
92
+ ```
93
+ require 'libmagic_rb'
94
+
95
+ cookie = LibmagicRb.new(
96
+ db: '/usr/share/file/magic.mgc',
97
+ file: '/usr/share/backgrounds/vienna-5164602.jpg',
98
+ mode: LibmagicRb::NONE
99
+ )
100
+
101
+ cookie.check() # => "JPEG image data, JFIF standard 1.01, resolution (DPI), density 300x300, segment length 16, Exif Standard: [TIFF image data, big-endian, direntries=4, manufacturer=NIKON CORPORATION, model=NIKON D5300], baseline, precision 8, 5959x3973, components 3""
102
+ cookie.close() # => #<LibmagicRb:0x000055fa77699818 @closed=true, @db="/home/sourav/.gem/ruby/3.0.0/gems/libmagic_rb-0.1.0/data/magic.mgc", @file="/usr/share/backgrounds/vienna-5164602.jpg", @mode=1106>
103
+ cookie.closed?() # => true
104
+ ```
105
+ Surely, you can automatically get db path if you pass nil to it. But If you happen to remove the database file or you are unsure, `db: nil` will not work (so will linux's file command).
106
+ Specifying the path gives you the privilege to pass a locally stored database.
107
+
108
+ Do note that there should be version match for the magic files, otherwise it will raise `LibmagicRb::InvalidDBError`.
109
+
110
+ ### Example 3:
111
+ LibmagicRb also provides a handy singleton method `:check`. You just need to pass the filename and modes:
112
+
113
+ ```
114
+ require 'libmagic_rb'
115
+
116
+ LibmagicRb.check(file: '/dev/zero', mode: LibmagicRb::MAGIC_NONE) #=> "character special (1/5)"
117
+ LibmagicRb.check(file: '/', mode: LibmagicRb::MAGIC_NONE) # => "directory"
118
+ LibmagicRb.check(file: '/') # => "inode/directory; charset=binary"
119
+ ```
120
+
121
+ Optional:
122
+ + You can use the db: keyword for a custom path. By default it's set to nil. And as mentioned above, nil = automatically find the db from the system.
123
+ + The `mode:` key is optional, by default it's set to `LibmagicRb::MAGIC_MIME | LibmagicRb::MAGIC_CHECK | LibmagicRb::MAGIC_SYMLINK`.
124
+
125
+ Notes:
126
+ + It's really **mandatory** to close the cookie (`cookie.close()`) when you are done with the cookie. Otherwise, you rely on the GC and that can cause various problems.
127
+ You can't also use the file after it's closed.
128
+ + You can change the file and db on the fly. But you can't change the mode. The mode can be assigned only with LibmagicRb.new(db: ..., file: ..., mode: ...)
129
+ + To list all the modes, please refer to the [man page](https://man7.org/linux/man-pages/man3/magic_getflags.3.html).
130
+
131
+ ### Open Modes
132
+ Files can be opened in various modes. You can use this short hand to see the supported modes:
133
+
134
+ ```
135
+ LibmagicRb.lsmodes # => {:MAGIC_NONE=>0, :MAGIC_DEBUG=>1, :MAGIC_SYMLINK=>2, :MAGIC_COMPRESS=>4, :MAGIC_DEVICES=>8, :MAGIC_MIME_TYPE=>16, :MAGIC_MIME_ENCODING=>1024, :MAGIC_MIME=>1040, :MAGIC_CONTINUE=>32, :MAGIC_CHECK=>64, :MAGIC_PRESERVE_ATIME=>128, :MAGIC_RAW=>256, :MAGIC_ERROR=>512, :MAGIC_APPLE=>2048, :MAGIC_EXTENSION=>16777216, :MAGIC_COMPRESS_TRANSP=>33554432, :MAGIC_NO_CHECK_APPTYPE=>32768, :MAGIC_NO_CHECK_CDF=>262144, :MAGIC_NO_CHECK_COMPRESS=>4096, :MAGIC_NO_CHECK_ELF=>65536, :MAGIC_NO_CHECK_ENCODING=>2097152, :MAGIC_NO_CHECK_SOFT=>16384, :MAGIC_NO_CHECK_TAR=>8192, :MAGIC_NO_CHECK_TEXT=>131072, :MAGIC_NO_CHECK_TOKENS=>1048576, :MAGIC_NO_CHECK_CSV=>524288, :MAGIC_NO_CHECK_JSON=>4194304}
136
+ ```
137
+
138
+ Note:
139
+ + Some keys can be missing or can have modified values, depending on your libmagic version.
140
+
141
+ ### Parameters
142
+
143
+ #### Listing parameters
144
+
145
+ ```
146
+ LibmagicRb.lsparams # => {:MAGIC_PARAM_INDIR_MAX=>0, :MAGIC_PARAM_NAME_MAX=>1, :MAGIC_PARAM_ELF_NOTES_MAX=>4, :MAGIC_PARAM_ELF_PHNUM_MAX=>2, :MAGIC_PARAM_ELF_SHNUM_MAX=>3, :MAGIC_PARAM_REGEX_MAX=>5, :MAGIC_PARAM_BYTES_MAX=>6}
147
+ ```
148
+
149
+ Note:
150
+ + Some keys can be missing or can have modified values, depending on your libmagic version.
151
+
152
+ #### Getting parameters
153
+
154
+ ```
155
+ cookie.getparam(LibmagicRb::MAGIC_PARAM_REGEX_MAX) # => 8192; but can differ. Returns nil on error.
156
+ ```
157
+
158
+ #### Setting parameters
159
+ ```
160
+ cookie.setparam(LibmagicRb::MAGIC_PARAM_REGEX_MAX, 2 ** 14) # => 16384; but can differ. Returns nil on error.
161
+ ```
162
+
163
+ #### Notes:
164
+
165
+ + To get the parameters, you can refer to the [man page](https://man7.org/linux/man-pages/man3/magic_getflags.3.html).
166
+ + Cookie setparam returns the value after getting the param as well. So you don't need to confirm by calling getparam() again.
167
+ + The maximum size depends on the parameter. But the value that can be passed should not be more than 2 ** 32.
168
+
169
+ ## Errors
170
+ The following errors are implemented and raised on appropriate situation:
171
+
172
+ 1. LibmagicRb::FileNotFound: When the file is not found.
173
+ 2. LibmagicRb::FileUnreadable: When the file is unreadable.
174
+ 3. LibmagicRb::InvalidDBError: When the database given is invalid.
175
+ 4. LibmagicRb::IsDirError: When the database path is a directory.
176
+ 5. LibmagicRb::FileClosedError: When the file is already closed (closed?()) but you are trying to access the cookie.
177
+
178
+ ## Development
179
+
180
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version.
181
+
182
+ ## Contributing
183
+
184
+ Bug reports and pull requests are welcome on GitHub at [https://github.com/cybergizer-hq/LibmagicRb](https://github.com/cybergizer-hq/LibmagicRb) This project is intended to be a safe, welcoming space for collaboration.
185
+
186
+ ## License
187
+
188
+ The gem is available as open-source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/bin/console ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ begin
5
+ require "libmagic_rb"
6
+ rescue LoadError
7
+ abort <<~EOF
8
+ Can't load `libmagic_rb'.
9
+ Please make sure to install this gem before loading this into irb!
10
+ EOF
11
+ end
12
+
13
+ require "irb"
14
+ puts ":: Loaded LibmagicRb Version: #{LibmagicRb::VERSION}"
15
+
16
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,4 @@
1
+ #define RB_UNWRAP(cookie) \
2
+ magic_t *cookie ; \
3
+ TypedData_Get_Struct(self, magic_t, &fileType, cookie) ; \
4
+ if(!*cookie) rb_raise(rb_eFileClosedError, "Magic cookie already closed") ;
@@ -0,0 +1,9 @@
1
+ require 'mkmf'
2
+
3
+ $LDFLAGS << ' -lmagic'
4
+ $CFLAGS << ' -Os'
5
+
6
+ abort "\e[1;31m*** Can't find magic.h ***\e[0m" unless have_header('magic.h')
7
+ abort "\e[1;31m*** Can't find magic_open() in magic.h ***\e[0m" unless have_library('magic', 'magic_open')
8
+
9
+ create_makefile 'libmagic_rb/main'
@@ -0,0 +1,111 @@
1
+ VALUE _closeGlobal_(volatile VALUE self) {
2
+ RB_UNWRAP(cookie) ;
3
+
4
+ magic_close(*cookie) ;
5
+ *cookie = NULL ;
6
+ rb_ivar_set(self, rb_intern("@closed"), Qtrue) ;
7
+ return self ;
8
+ }
9
+
10
+ VALUE _loadGlobal_(volatile VALUE self, volatile VALUE dbPath) {
11
+ char *databasePath = NULL ;
12
+
13
+ if (RB_TYPE_P(dbPath, T_STRING)) {
14
+ databasePath = StringValuePtr(dbPath) ;
15
+ rb_iv_set(self, "@db", dbPath) ;
16
+ } else if(RB_TYPE_P(dbPath, T_STRING)) {
17
+ rb_iv_set(self, "@db", Qnil) ;
18
+ }
19
+
20
+ // Check if the database is a valid file or not
21
+ // Raises ruby error which will return.
22
+ RB_UNWRAP(cookie) ;
23
+
24
+ if(databasePath) magic_validate_db(*cookie, databasePath) ;
25
+ magic_load(*cookie, databasePath) ;
26
+
27
+ return self ;
28
+ }
29
+
30
+ VALUE _checkGlobal_(volatile VALUE self) {
31
+ RB_UNWRAP(cookie) ;
32
+
33
+ // Database path
34
+ VALUE db = rb_iv_get(self, "@db") ;
35
+
36
+ char *database = NULL ;
37
+ if(RB_TYPE_P(db, T_STRING)) {
38
+ database = StringValuePtr(db) ;
39
+ }
40
+
41
+ // File path
42
+ VALUE f = rb_iv_get(self, "@file") ;
43
+ char *file = StringValuePtr(f) ;
44
+
45
+ if(database) magic_validate_db(*cookie, database) ;
46
+ magic_load(*cookie, database) ;
47
+
48
+ fileReadable(file) ;
49
+ const char *mt = magic_file(*cookie, file) ;
50
+
51
+ return mt ? rb_str_new_cstr(mt) : Qnil ;
52
+ }
53
+
54
+ VALUE _getParamGlobal_(volatile VALUE self, volatile VALUE param) {
55
+ RB_UNWRAP(cookie) ;
56
+
57
+ unsigned int _param = NUM2UINT(param) ;
58
+ unsigned long value ;
59
+
60
+ int status = magic_getparam(*cookie, _param, &value) ;
61
+ if (status) return Qnil ;
62
+ return ULONG2NUM(value) ;
63
+ }
64
+
65
+ VALUE _setParamGlobal_(volatile VALUE self, volatile VALUE param, volatile VALUE paramVal) {
66
+ unsigned int _param = NUM2UINT(param) ;
67
+ unsigned long _paramVal = NUM2ULONG(paramVal) ;
68
+
69
+ RB_UNWRAP(cookie) ;
70
+
71
+ unsigned long value ;
72
+ magic_setparam(*cookie, _param, &_paramVal) ;
73
+
74
+ int status = magic_getparam(*cookie, _param, &value) ;
75
+
76
+ if (status) return Qnil ;
77
+ return ULONG2NUM((int)value) ;
78
+ }
79
+
80
+ VALUE _bufferGlobal_(volatile VALUE self, volatile VALUE string) {
81
+ RB_UNWRAP(cookie) ;
82
+
83
+ char *buffer = StringValuePtr(string) ;
84
+ const char *buf = magic_buffer(*cookie, buffer, sizeof(buffer)) ;
85
+
86
+ return rb_str_new_cstr(buf) ;
87
+ }
88
+
89
+ VALUE _listGlobal_(volatile VALUE self) {
90
+ RB_UNWRAP(cookie) ;
91
+
92
+ VALUE db = rb_iv_get(self, "@db") ;
93
+ char *database = StringValuePtr(db) ;
94
+
95
+ int status = magic_list(*cookie, database) ;
96
+ return INT2FIX(status) ;
97
+ }
98
+
99
+ VALUE _setflagsGlobal_(volatile VALUE self, volatile VALUE flags) {
100
+ unsigned int flag = NUM2UINT(flags) ;
101
+
102
+ RB_UNWRAP(cookie) ;
103
+ int status = magic_setflags(*cookie, flag) ;
104
+
105
+ if (status) {
106
+ return Qnil ;
107
+ } else {
108
+ rb_ivar_set(self, rb_intern("@mode"), flags) ;
109
+ return flags ;
110
+ }
111
+ }
@@ -0,0 +1,232 @@
1
+ #include <magic.h>
2
+ #include <stdio.h>
3
+ #include <unistd.h>
4
+ #include "ruby.h"
5
+
6
+ /*
7
+ * LibmagicRB Header files
8
+ */
9
+ #include "modes.h"
10
+ #include "params.h"
11
+ #include "definitions.h"
12
+
13
+ /*
14
+ * Errors
15
+ */
16
+ VALUE rb_eFileNotFoundError ;
17
+ VALUE rb_eFileNotReadableError ;
18
+ VALUE rb_eInvalidDBError ;
19
+ VALUE rb_eIsDirError ;
20
+ VALUE rb_eFileClosedError ;
21
+
22
+ // Garbage collect
23
+ void file_free(void **data) {
24
+ if(*data) {
25
+ magic_close(*data) ;
26
+ *data = NULL ;
27
+ }
28
+
29
+ free(data) ;
30
+ }
31
+
32
+ // Filetype
33
+ static rb_data_type_t fileType = {
34
+ .wrap_struct_name = "file",
35
+
36
+ .function = {
37
+ .dmark = NULL,
38
+ .dfree = file_free,
39
+ },
40
+
41
+ .data = NULL,
42
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
43
+ } ;
44
+
45
+ #include "validations.h"
46
+ #include "func.h"
47
+
48
+ VALUE _check_(volatile VALUE obj, volatile VALUE args) {
49
+ if(!RB_TYPE_P(args, T_HASH)) {
50
+ rb_raise(rb_eArgError, "Expected hash as argument.") ;
51
+ }
52
+
53
+ // Database Path
54
+ VALUE argDBPath = rb_hash_aref(args, ID2SYM(rb_intern("db"))) ;
55
+
56
+ char *databasePath ;
57
+ if (RB_TYPE_P(argDBPath, T_NIL)) {
58
+ databasePath = NULL ;
59
+ } else if (!RB_TYPE_P(argDBPath, T_STRING)) {
60
+ rb_raise(rb_eArgError, "Database name must be an instance of String.") ;
61
+ } else {
62
+ databasePath = StringValuePtr(argDBPath) ;
63
+ }
64
+
65
+ // File path
66
+ VALUE argFilePath = rb_hash_aref(args, ID2SYM(rb_intern("file"))) ;
67
+ if (RB_TYPE_P(argFilePath, T_NIL)) {
68
+ rb_raise(rb_eArgError, "Expected `file:\" key as a string, got nil instead") ;
69
+ } else if (!RB_TYPE_P(argFilePath, T_STRING)) {
70
+ rb_raise(rb_eArgError, "Filename must be an instance of String.") ;
71
+ }
72
+ char *checkPath = StringValuePtr(argFilePath) ;
73
+
74
+ // Modes
75
+ VALUE argModes = rb_hash_aref(args, ID2SYM(rb_intern("mode"))) ;
76
+ unsigned int modes ;
77
+ if(RB_TYPE_P(argModes, T_NIL)) {
78
+ modes = MAGIC_MIME | MAGIC_CHECK | MAGIC_SYMLINK ;
79
+ } else if (!RB_TYPE_P(argModes, T_FIXNUM)) {
80
+ rb_raise(rb_eArgError, "Modes must be an instance of Integer. Check LibmagicRb.constants() or LibmagicRb.lsmodes().") ;
81
+ } else {
82
+ modes = FIX2UINT(argModes) ;
83
+ }
84
+
85
+ // Checks
86
+ struct magic_set *magic = magic_open(modes) ;
87
+
88
+ // Check if the database is a valid file or not
89
+ // Raises ruby error which will return.
90
+ fileReadable(checkPath) ;
91
+
92
+ if(databasePath) {
93
+ magic_validate_db(magic, databasePath) ;
94
+ }
95
+
96
+ magic_load(magic, databasePath) ;
97
+
98
+ const char *mt = magic_file(magic, checkPath) ;
99
+
100
+ VALUE retVal = mt ? rb_str_new_cstr(mt) : Qnil ;
101
+ magic_close(magic) ;
102
+
103
+ return retVal ;
104
+ }
105
+
106
+ VALUE rb_libmagicRb_initialize(volatile VALUE self, volatile VALUE args) {
107
+ // Database Path
108
+ if(!RB_TYPE_P(args, T_HASH)) {
109
+ rb_raise(rb_eArgError, "Expected hash as argument.") ;
110
+ }
111
+
112
+ VALUE argDBPath = rb_hash_aref(args, ID2SYM(rb_intern("db"))) ;
113
+
114
+ char *databasePath ;
115
+ if (RB_TYPE_P(argDBPath, T_NIL)) {
116
+ databasePath = NULL ;
117
+ rb_ivar_set(self, rb_intern("@db"), Qnil) ;
118
+ } else if (!RB_TYPE_P(argDBPath, T_STRING)) {
119
+ rb_raise(rb_eArgError, "Database name must be an instance of String.") ;
120
+ } else {
121
+ databasePath = StringValuePtr(argDBPath) ;
122
+ rb_ivar_set(self, rb_intern("@db"), argDBPath) ;
123
+ }
124
+
125
+ // File path
126
+ VALUE argFilePath = rb_hash_aref(args, ID2SYM(rb_intern("file"))) ;
127
+ if (RB_TYPE_P(argFilePath, T_NIL)) {
128
+ rb_raise(rb_eArgError, "Expected `file:\" key as a string, got nil instead") ;
129
+ } else if (!RB_TYPE_P(argFilePath, T_STRING)) {
130
+ rb_raise(rb_eArgError, "Filename must be an instance of String.") ;
131
+ }
132
+ rb_ivar_set(self, rb_intern("@file"), argFilePath) ;
133
+
134
+ // Modes
135
+ VALUE argModes = rb_hash_aref(args, ID2SYM(rb_intern("mode"))) ;
136
+ unsigned int modes ;
137
+ if(RB_TYPE_P(argModes, T_NIL)) {
138
+ modes = MAGIC_MIME | MAGIC_CHECK | MAGIC_SYMLINK ;
139
+ } else if (!RB_TYPE_P(argModes, T_FIXNUM)) {
140
+ rb_raise(rb_eArgError, "Modes must be an instance of Integer. Check LibmagicRb.constants() or LibmagicRb.lsmodes().") ;
141
+ } else {
142
+ modes = FIX2UINT(argModes) ;
143
+ }
144
+ rb_ivar_set(self, rb_intern("@mode"), UINT2NUM(modes)) ;
145
+
146
+ rb_ivar_set(self, rb_intern("@closed"), Qfalse) ;
147
+
148
+ RB_UNWRAP(cookie) ;
149
+ magic_setflags(*cookie, modes) ;
150
+
151
+ return self ;
152
+ }
153
+
154
+ VALUE initAlloc(volatile VALUE self) {
155
+ magic_t *cookie ;
156
+ cookie = malloc(sizeof(*cookie)) ;
157
+ *cookie = magic_open(0) ;
158
+
159
+ return TypedData_Wrap_Struct(self, &fileType, cookie) ;
160
+ }
161
+
162
+ void Init_main() {
163
+ rb_global_variable(&rb_eFileNotFoundError) ;
164
+ rb_global_variable(&rb_eFileNotReadableError) ;
165
+ rb_global_variable(&rb_eInvalidDBError) ;
166
+ rb_global_variable(&rb_eIsDirError) ;
167
+ rb_global_variable(&rb_eFileClosedError) ;
168
+
169
+ /*
170
+ * Libmagic Errors
171
+ */
172
+ VALUE cLibmagicRb = rb_define_class("LibmagicRb", rb_cObject) ;
173
+
174
+ rb_eFileNotFoundError = rb_define_class_under(cLibmagicRb, "FileNotFound", rb_eRuntimeError) ;
175
+ rb_eFileNotReadableError = rb_define_class_under(cLibmagicRb, "FileUnreadable", rb_eRuntimeError) ;
176
+ rb_eInvalidDBError = rb_define_class_under(cLibmagicRb, "InvalidDBError", rb_eRuntimeError) ;
177
+ rb_eIsDirError = rb_define_class_under(cLibmagicRb, "IsDirError", rb_eRuntimeError) ;
178
+ rb_eFileClosedError = rb_define_class_under(cLibmagicRb, "FileClosedError", rb_eRuntimeError) ;
179
+
180
+ /*
181
+ * Constants
182
+ */
183
+ modes(cLibmagicRb) ;
184
+ params(cLibmagicRb) ;
185
+
186
+ char version[6] ;
187
+ sprintf(version, "%0.2f", magic_version() / 100.0) ;
188
+ rb_define_const(cLibmagicRb, "MAGIC_VERSION", rb_str_new_cstr(version)) ;
189
+
190
+ /*
191
+ * Singleton Methods
192
+ */
193
+ rb_define_singleton_method(cLibmagicRb, "check", _check_, 1) ;
194
+ rb_define_singleton_method(cLibmagicRb, "lsmodes", lsmodes, 0) ;
195
+ rb_define_singleton_method(cLibmagicRb, "lsparams", lsparams, 0) ;
196
+
197
+ /*
198
+ * Instance Methods
199
+ */
200
+ rb_define_alloc_func(cLibmagicRb, initAlloc) ;
201
+
202
+ // LibmagicRb.new()
203
+ rb_define_method(cLibmagicRb, "initialize", rb_libmagicRb_initialize, 1) ;
204
+
205
+ // Attributes
206
+ rb_define_attr(cLibmagicRb, "closed", 1, 0) ;
207
+ rb_define_attr(cLibmagicRb, "mode", 1, 0) ;
208
+ rb_define_attr(cLibmagicRb, "file", 1, 1) ;
209
+ rb_define_attr(cLibmagicRb, "db", 1, 1) ;
210
+
211
+ // Close database
212
+ rb_define_method(cLibmagicRb, "close", _closeGlobal_, 0) ;
213
+ rb_define_alias(cLibmagicRb, "closed?", "closed") ;
214
+
215
+ // Load database
216
+ rb_define_method(cLibmagicRb, "load", _loadGlobal_, 1) ;
217
+
218
+ // Check for file mimetype
219
+ rb_define_method(cLibmagicRb, "check", _checkGlobal_, 0) ;
220
+
221
+ // Get and set params
222
+ rb_define_method(cLibmagicRb, "getparam", _getParamGlobal_, 1) ;
223
+ rb_define_method(cLibmagicRb, "setparam", _setParamGlobal_, 2) ;
224
+
225
+ // Set modes dynamically
226
+ rb_define_method(cLibmagicRb, "setflags", _setflagsGlobal_, 1) ;
227
+ rb_define_method(cLibmagicRb, "mode=", _setflagsGlobal_, 1) ;
228
+
229
+ // Miscellaneous
230
+ rb_define_method(cLibmagicRb, "magic_buffer", _bufferGlobal_, 1) ;
231
+ rb_define_method(cLibmagicRb, "magic_list", _listGlobal_, 0) ;
232
+ }
@@ -0,0 +1,77 @@
1
+ // In the older versions, there were some missing constants. Don't define them at compile time.
2
+
3
+ void modes(volatile VALUE rb_klass) {
4
+ rb_define_const(rb_klass, "MAGIC_NONE", INT2FIX(MAGIC_NONE)) ;
5
+ rb_define_const(rb_klass, "MAGIC_DEBUG", INT2FIX(MAGIC_DEBUG)) ;
6
+ rb_define_const(rb_klass, "MAGIC_SYMLINK", INT2FIX(MAGIC_SYMLINK)) ;
7
+ rb_define_const(rb_klass, "MAGIC_COMPRESS", INT2FIX(MAGIC_COMPRESS)) ;
8
+ rb_define_const(rb_klass, "MAGIC_DEVICES", INT2FIX(MAGIC_DEVICES)) ;
9
+ rb_define_const(rb_klass, "MAGIC_MIME_TYPE", INT2FIX(MAGIC_MIME_TYPE)) ;
10
+ rb_define_const(rb_klass, "MAGIC_MIME_ENCODING", INT2FIX(MAGIC_MIME_ENCODING)) ;
11
+ rb_define_const(rb_klass, "MAGIC_MIME", INT2FIX(MAGIC_MIME)) ;
12
+ rb_define_const(rb_klass, "MAGIC_CONTINUE", INT2FIX(MAGIC_CONTINUE)) ;
13
+ rb_define_const(rb_klass, "MAGIC_CHECK", INT2FIX(MAGIC_CHECK)) ;
14
+ rb_define_const(rb_klass, "MAGIC_PRESERVE_ATIME", INT2FIX(MAGIC_PRESERVE_ATIME)) ;
15
+ rb_define_const(rb_klass, "MAGIC_RAW", INT2FIX(MAGIC_RAW)) ;
16
+ rb_define_const(rb_klass, "MAGIC_ERROR", INT2FIX(MAGIC_ERROR)) ;
17
+ rb_define_const(rb_klass, "MAGIC_APPLE", INT2FIX(MAGIC_APPLE)) ;
18
+ rb_define_const(rb_klass, "MAGIC_EXTENSION", INT2FIX(MAGIC_EXTENSION)) ;
19
+ rb_define_const(rb_klass, "MAGIC_COMPRESS_TRANSP", INT2FIX(MAGIC_COMPRESS_TRANSP)) ;
20
+ rb_define_const(rb_klass, "MAGIC_NO_CHECK_APPTYPE", INT2FIX(MAGIC_NO_CHECK_APPTYPE)) ;
21
+ rb_define_const(rb_klass, "MAGIC_NO_CHECK_CDF", INT2FIX(MAGIC_NO_CHECK_CDF)) ;
22
+ rb_define_const(rb_klass, "MAGIC_NO_CHECK_COMPRESS", INT2FIX(MAGIC_NO_CHECK_COMPRESS)) ;
23
+ rb_define_const(rb_klass, "MAGIC_NO_CHECK_ELF", INT2FIX(MAGIC_NO_CHECK_ELF)) ;
24
+ rb_define_const(rb_klass, "MAGIC_NO_CHECK_ENCODING", INT2FIX(MAGIC_NO_CHECK_ENCODING)) ;
25
+ rb_define_const(rb_klass, "MAGIC_NO_CHECK_SOFT", INT2FIX(MAGIC_NO_CHECK_SOFT)) ;
26
+ rb_define_const(rb_klass, "MAGIC_NO_CHECK_TAR", INT2FIX(MAGIC_NO_CHECK_TAR)) ;
27
+ rb_define_const(rb_klass, "MAGIC_NO_CHECK_TEXT", INT2FIX(MAGIC_NO_CHECK_TEXT)) ;
28
+ rb_define_const(rb_klass, "MAGIC_NO_CHECK_TOKENS", INT2FIX(MAGIC_NO_CHECK_TOKENS)) ;
29
+
30
+ #ifdef MAGIC_NO_CHECK_JSON
31
+ rb_define_const(rb_klass, "MAGIC_NO_CHECK_JSON", INT2FIX(MAGIC_NO_CHECK_JSON)) ;
32
+ #endif
33
+
34
+ #ifdef MAGIC_NO_CHECK_CSV
35
+ rb_define_const(rb_klass, "MAGIC_NO_CHECK_CSV", INT2FIX(MAGIC_NO_CHECK_CSV)) ;
36
+ #endif
37
+ }
38
+
39
+ VALUE lsmodes(volatile VALUE obj) {
40
+ VALUE hash = rb_hash_new() ;
41
+
42
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_NONE")), INT2FIX(MAGIC_NONE)) ;
43
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_DEBUG")), INT2FIX(MAGIC_DEBUG)) ;
44
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_SYMLINK")), INT2FIX(MAGIC_SYMLINK)) ;
45
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_COMPRESS")), INT2FIX(MAGIC_COMPRESS)) ;
46
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_DEVICES")), INT2FIX(MAGIC_DEVICES)) ;
47
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_MIME_TYPE")), INT2FIX(MAGIC_MIME_TYPE)) ;
48
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_MIME_ENCODING")), INT2FIX(MAGIC_MIME_ENCODING)) ;
49
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_MIME")), INT2FIX(MAGIC_MIME)) ;
50
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_CONTINUE")), INT2FIX(MAGIC_CONTINUE)) ;
51
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_CHECK")), INT2FIX(MAGIC_CHECK)) ;
52
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_PRESERVE_ATIME")), INT2FIX(MAGIC_PRESERVE_ATIME)) ;
53
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_RAW")), INT2FIX(MAGIC_RAW)) ;
54
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_ERROR")), INT2FIX(MAGIC_ERROR)) ;
55
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_APPLE")), INT2FIX(MAGIC_APPLE)) ;
56
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_EXTENSION")), INT2FIX(MAGIC_EXTENSION)) ;
57
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_COMPRESS_TRANSP")), INT2FIX(MAGIC_COMPRESS_TRANSP)) ;
58
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_NO_CHECK_APPTYPE")), INT2FIX(MAGIC_NO_CHECK_APPTYPE)) ;
59
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_NO_CHECK_CDF")), INT2FIX(MAGIC_NO_CHECK_CDF)) ;
60
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_NO_CHECK_COMPRESS")), INT2FIX(MAGIC_NO_CHECK_COMPRESS)) ;
61
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_NO_CHECK_ELF")), INT2FIX(MAGIC_NO_CHECK_ELF)) ;
62
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_NO_CHECK_ENCODING")), INT2FIX(MAGIC_NO_CHECK_ENCODING)) ;
63
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_NO_CHECK_SOFT")), INT2FIX(MAGIC_NO_CHECK_SOFT)) ;
64
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_NO_CHECK_TAR")), INT2FIX(MAGIC_NO_CHECK_TAR)) ;
65
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_NO_CHECK_TEXT")), INT2FIX(MAGIC_NO_CHECK_TEXT)) ;
66
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_NO_CHECK_TOKENS")), INT2FIX(MAGIC_NO_CHECK_TOKENS)) ;
67
+
68
+ #ifdef MAGIC_NO_CHECK_CSV
69
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_NO_CHECK_CSV")), INT2FIX(MAGIC_NO_CHECK_CSV)) ;
70
+ #endif
71
+
72
+ #ifdef MAGIC_NO_CHECK_CSV
73
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_NO_CHECK_JSON")), INT2FIX(MAGIC_NO_CHECK_JSON)) ;
74
+ #endif
75
+
76
+ return hash ;
77
+ }
@@ -0,0 +1,29 @@
1
+ void params(volatile VALUE rb_klass) {
2
+ rb_define_const(rb_klass, "MAGIC_PARAM_INDIR_MAX", UINT2NUM(MAGIC_PARAM_INDIR_MAX)) ;
3
+ rb_define_const(rb_klass, "MAGIC_PARAM_NAME_MAX", UINT2NUM(MAGIC_PARAM_NAME_MAX)) ;
4
+ rb_define_const(rb_klass, "MAGIC_PARAM_ELF_NOTES_MAX", UINT2NUM(MAGIC_PARAM_ELF_NOTES_MAX)) ;
5
+ rb_define_const(rb_klass, "MAGIC_PARAM_ELF_PHNUM_MAX", UINT2NUM(MAGIC_PARAM_ELF_PHNUM_MAX)) ;
6
+ rb_define_const(rb_klass, "MAGIC_PARAM_ELF_SHNUM_MAX", UINT2NUM(MAGIC_PARAM_ELF_SHNUM_MAX)) ;
7
+ rb_define_const(rb_klass, "MAGIC_PARAM_REGEX_MAX", UINT2NUM(MAGIC_PARAM_REGEX_MAX)) ;
8
+
9
+ #ifdef MAGIC_PARAM_BYTES_MAX
10
+ rb_define_const(rb_klass, "MAGIC_PARAM_BYTES_MAX", UINT2NUM(MAGIC_PARAM_BYTES_MAX)) ;
11
+ #endif
12
+ }
13
+
14
+ VALUE lsparams(volatile VALUE obj) {
15
+ VALUE hash = rb_hash_new() ;
16
+
17
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_PARAM_INDIR_MAX")), UINT2NUM(MAGIC_PARAM_INDIR_MAX)) ;
18
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_PARAM_NAME_MAX")), UINT2NUM(MAGIC_PARAM_NAME_MAX)) ;
19
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_PARAM_ELF_NOTES_MAX")), UINT2NUM(MAGIC_PARAM_ELF_NOTES_MAX)) ;
20
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_PARAM_ELF_PHNUM_MAX")), UINT2NUM(MAGIC_PARAM_ELF_PHNUM_MAX)) ;
21
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_PARAM_ELF_SHNUM_MAX")), UINT2NUM(MAGIC_PARAM_ELF_SHNUM_MAX)) ;
22
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_PARAM_REGEX_MAX")), UINT2NUM(MAGIC_PARAM_REGEX_MAX)) ;
23
+
24
+ #ifdef MAGIC_PARAM_BYTES_MAX
25
+ rb_hash_aset(hash, ID2SYM(rb_intern("MAGIC_PARAM_BYTES_MAX")), UINT2NUM(MAGIC_PARAM_BYTES_MAX)) ;
26
+ #endif
27
+
28
+ return hash ;
29
+ }
@@ -0,0 +1,23 @@
1
+ void fileReadable(char *filePath) {
2
+ if(access(filePath, F_OK)) rb_raise(rb_eFileNotFoundError, "%s", filePath) ;
3
+ if(access(filePath, R_OK)) rb_raise(rb_eFileNotReadableError, "%s", filePath) ;
4
+ }
5
+
6
+ void magic_validate_db(magic_t cookie, char *databasePath) {
7
+ struct stat statbuf ;
8
+
9
+ if (stat(databasePath, &statbuf) != 0)
10
+ rb_raise(rb_eFileNotFoundError, "%s", databasePath) ;
11
+
12
+ if(S_ISDIR(statbuf.st_mode))
13
+ rb_raise(rb_eIsDirError, "%s", databasePath) ;
14
+
15
+ if(access(databasePath, R_OK)) rb_raise(rb_eFileNotReadableError, "%s", databasePath) ;
16
+
17
+ int validFile = magic_check(cookie, databasePath) ;
18
+
19
+ if (validFile != 0) {
20
+ const char *err = magic_error(cookie) ;
21
+ rb_raise(rb_eInvalidDBError, "%s (%s is not a valid magic file)", err, databasePath) ;
22
+ }
23
+ }
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "libmagic_rb/version"
4
+ require "libmagic_rb/main"
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class LibmagicRb
4
+ VERSION = "0.1.0-alpha"
5
+ end
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: libmagic_rb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0.pre.alpha
5
+ platform: ruby
6
+ authors:
7
+ - Cybergizer
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-08-19 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Check filetype with libmagic
14
+ email:
15
+ - sourav.goswami@cybergizer.com
16
+ executables: []
17
+ extensions:
18
+ - ext/libmagic/extconf.rb
19
+ extra_rdoc_files:
20
+ - README.md
21
+ files:
22
+ - LICENSE.txt
23
+ - README.md
24
+ - bin/console
25
+ - bin/setup
26
+ - ext/libmagic/definitions.h
27
+ - ext/libmagic/extconf.rb
28
+ - ext/libmagic/func.h
29
+ - ext/libmagic/magic.c
30
+ - ext/libmagic/modes.h
31
+ - ext/libmagic/params.h
32
+ - ext/libmagic/validations.h
33
+ - lib/libmagic_rb.rb
34
+ - lib/libmagic_rb/version.rb
35
+ homepage: https://github.com/Cybergizer-hq/libmagic_rb/
36
+ licenses:
37
+ - MIT
38
+ metadata: {}
39
+ post_install_message:
40
+ rdoc_options: []
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 1.9.0
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">"
51
+ - !ruby/object:Gem::Version
52
+ version: 1.3.1
53
+ requirements: []
54
+ rubygems_version: 3.0.8
55
+ signing_key:
56
+ specification_version: 4
57
+ summary: Check filetype with libmagic
58
+ test_files: []