tsalzer-richfile 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +15 -13
- data/VERSION.yml +2 -2
- data/lib/richfile.rb +3 -1
- data/lib/richfile/base.rb +6 -44
- data/lib/richfile/digests.rb +280 -0
- data/lib/richfile/mimetype.rb +54 -0
- metadata +4 -2
data/README.rdoc
CHANGED
@@ -7,10 +7,12 @@ A simple gem which adds some additional methods to File objects.
|
|
7
7
|
gem install tsalzer-richfile --source http://gems.github.com
|
8
8
|
|
9
9
|
|
10
|
-
== What is
|
10
|
+
== What is Richfile?
|
11
11
|
|
12
|
-
Richfile extends the Ruby built-in File instances with some
|
12
|
+
Richfile extends the Ruby built-in File instances with some sometimes
|
13
13
|
useful attributes.
|
14
|
+
- +size+ attribute to cache the file size in a File object
|
15
|
+
- OpenSSL digest attributes like <code>md5</code> and <code>sha1</code> (for all available digests)
|
14
16
|
|
15
17
|
Note that there is no built-in magic to keep the once-fetched attributes
|
16
18
|
in sync with the effective attributes of the real files.
|
@@ -25,23 +27,23 @@ Now, every new File object has a list of additional attributes. Whenever you
|
|
25
27
|
access the attributes the first time, the data is pulled from the file system
|
26
28
|
and cached in the File object.
|
27
29
|
|
28
|
-
If you need to refresh the data, either call
|
29
|
-
attribute you used before, or
|
30
|
+
If you need to refresh the data, either call <code>refresh!</code>, which updates every
|
31
|
+
attribute you used before, or <code>refresh_all!</code>, which updates each of the cached
|
30
32
|
attributes. When you are just interested in a single attribute, call the
|
31
|
-
attribute with an added bang (like
|
33
|
+
attribute with an added bang (like <code>size!</code>).
|
32
34
|
|
33
35
|
== Building a new Gem
|
34
36
|
|
35
|
-
To create a new gem, you need to install the
|
36
|
-
http://
|
37
|
-
|
37
|
+
To create a new gem, you need to install the jeweler gem (see
|
38
|
+
http://github.com/technicalpickles/jeweler/tree/master). If this is done, you can
|
39
|
+
easily build a new gemspec with
|
38
40
|
|
39
|
-
rake
|
40
|
-
|
41
|
-
rake build_gemspec # update the gemspec
|
41
|
+
rake gemspec
|
42
|
+
gem build richfile.gemspec
|
42
43
|
|
43
|
-
|
44
|
-
|
44
|
+
This would create a new richfile-x.y.z.gem, which can easily be installed via
|
45
|
+
|
46
|
+
gem install richfile-x.y.z.gem
|
45
47
|
|
46
48
|
== License
|
47
49
|
|
data/VERSION.yml
CHANGED
data/lib/richfile.rb
CHANGED
data/lib/richfile/base.rb
CHANGED
@@ -1,55 +1,17 @@
|
|
1
|
-
require 'openssl'
|
2
|
-
|
3
1
|
# Extension to File.
|
4
2
|
module Richfile
|
5
|
-
if OpenSSL::OPENSSL_VERSION_NUMBER > 0x00908000
|
6
|
-
DIGESTS = %w(DSS1 MD2 MD4 MD5 RIPEMD160 SHA SHA1 SHA224 SHA256 SHA384 SHA512)
|
7
|
-
else
|
8
|
-
DIGESTS = %w(DSS1 MD2 MD4 MD5 RIPEMD160 SHA SHA1)
|
9
|
-
end
|
10
3
|
|
11
|
-
def self.digest_variants(digest)
|
12
|
-
digest_downcase = digest.downcase
|
13
|
-
digest_symbol = digest_downcase.to_sym
|
14
|
-
digest_bang = "#{digest_downcase}!".to_sym
|
15
|
-
digest_variable = "@#{digest_downcase}".to_sym
|
16
|
-
return digest_downcase, digest_symbol, digest_bang, digest_variable
|
17
|
-
end
|
18
|
-
|
19
4
|
# Methods to be included in File objects.
|
20
5
|
module Base
|
21
6
|
# size of the file in bytes.
|
22
7
|
attr_reader :size
|
23
8
|
|
24
|
-
# define attributes for all the digests in Richfile::DIGEST.
|
25
|
-
Richfile::DIGESTS.each do |digest|
|
26
|
-
d_downcase, d_sym, d_bang, d_var = Richfile.digest_variants(digest)
|
27
|
-
|
28
|
-
# message digest #{digest}
|
29
|
-
attr_reader d_sym
|
30
|
-
|
31
|
-
define_method d_sym do
|
32
|
-
instance_variable_set(d_var, File.open(path, 'r') do |f|
|
33
|
-
d = OpenSSL::Digest.new(digest)
|
34
|
-
d << f.read
|
35
|
-
d.hexdigest
|
36
|
-
end) unless instance_variable_get(d_var)
|
37
|
-
instance_variable_get(d_var)
|
38
|
-
end
|
39
|
-
define_method d_bang do
|
40
|
-
instance_variable_set(d_var, nil)
|
41
|
-
send d_sym
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
9
|
# refresh the Richfile added attributes.
|
46
10
|
# All the attributes referred once are loaded.
|
47
11
|
def refresh!
|
48
12
|
self.size! if @size
|
49
|
-
|
50
|
-
|
51
|
-
send d_bang if (instance_variable_get(d_var))
|
52
|
-
end
|
13
|
+
refresh_digests! if respond_to?(:refresh_all_digests!)
|
14
|
+
self.mimetype! if @mimetype
|
53
15
|
self
|
54
16
|
end
|
55
17
|
|
@@ -58,10 +20,8 @@ module Base
|
|
58
20
|
# You will most probably never need this method.
|
59
21
|
def refresh_all!
|
60
22
|
self.size!
|
61
|
-
|
62
|
-
|
63
|
-
send d_bang
|
64
|
-
end
|
23
|
+
refresh_all_digests! if respond_to?(:refresh_all_digests!)
|
24
|
+
self.mimetype!
|
65
25
|
self
|
66
26
|
end
|
67
27
|
|
@@ -88,6 +48,8 @@ end#Base
|
|
88
48
|
# include the Richfile::Base module into the File class.
|
89
49
|
def self.install
|
90
50
|
File.send :include, Richfile::Base
|
51
|
+
File.send :include, Richfile::Digests::Base
|
52
|
+
File.send :include, Richfile::Mimetype::Base
|
91
53
|
end
|
92
54
|
|
93
55
|
end#Richfile
|
@@ -0,0 +1,280 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
|
3
|
+
module Richfile
|
4
|
+
|
5
|
+
# Digest related functionality.
|
6
|
+
module Digests
|
7
|
+
|
8
|
+
if OpenSSL::OPENSSL_VERSION_NUMBER > 0x00908000
|
9
|
+
# all known digests for OpenSSL > 0.9.8
|
10
|
+
DIGESTS = %w(DSS1 MD2 MD4 MD5 RIPEMD160 SHA SHA1 SHA224 SHA256 SHA384 SHA512)
|
11
|
+
else
|
12
|
+
# all known digests for OpenSSL up to 0.9.8
|
13
|
+
DIGESTS = %w(DSS1 MD2 MD4 MD5 RIPEMD160 SHA SHA1)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.each_digest_symbols(&blk) #:nodoc:
|
17
|
+
DIGESTS.each do |digest|
|
18
|
+
digest_downcase = digest.downcase
|
19
|
+
digest_bang = "#{digest_downcase}!".to_sym
|
20
|
+
digest_variable = "@#{digest_downcase}".to_sym
|
21
|
+
|
22
|
+
blk.call(digest_bang, digest_variable)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Digest-related methods and attributes to be included in File objects.
|
27
|
+
module InstanceMethods
|
28
|
+
# DSS1 message digest.
|
29
|
+
attr_reader :dss1
|
30
|
+
# caching getter for DSS1 message digest.
|
31
|
+
def dss1
|
32
|
+
@dss1 = self.class.dss1(path) unless @dss1
|
33
|
+
@dss1
|
34
|
+
end
|
35
|
+
# getter for DSS1 message digest.
|
36
|
+
# This getter forces the digest to be reloaded.
|
37
|
+
def dss1!
|
38
|
+
@dss1 = nil
|
39
|
+
dss1
|
40
|
+
end
|
41
|
+
|
42
|
+
# MD2 message digest.
|
43
|
+
attr_reader :md2
|
44
|
+
# caching getter for MD2 message digest.
|
45
|
+
def md2
|
46
|
+
@md2 = self.class.md2(path) unless @md2
|
47
|
+
@md2
|
48
|
+
end
|
49
|
+
# getter for MD2 message digest.
|
50
|
+
# This getter forces the digest to be reloaded.
|
51
|
+
def md2!
|
52
|
+
@md2 = nil
|
53
|
+
md2
|
54
|
+
end
|
55
|
+
|
56
|
+
# MD4 message digest.
|
57
|
+
attr_reader :md4
|
58
|
+
# caching getter for MD4 message digest.
|
59
|
+
def md4
|
60
|
+
@md4 = self.class.md4(path) unless @md4
|
61
|
+
@md4
|
62
|
+
end
|
63
|
+
# getter for MD4 message digest.
|
64
|
+
# This getter forces the digest to be reloaded.
|
65
|
+
def md4!
|
66
|
+
@md4 = nil
|
67
|
+
md4
|
68
|
+
end
|
69
|
+
|
70
|
+
# MD5 message digest.
|
71
|
+
attr_reader :md5
|
72
|
+
# caching getter for MD5 message digest.
|
73
|
+
def md5
|
74
|
+
@md5 = self.class.md5(path) unless @md5
|
75
|
+
@md5
|
76
|
+
end
|
77
|
+
# getter for MD5 message digest.
|
78
|
+
# This getter forces the digest to be reloaded.
|
79
|
+
def md5!
|
80
|
+
@md5 = nil
|
81
|
+
md5
|
82
|
+
end
|
83
|
+
|
84
|
+
# RIPEMD160 message digest.
|
85
|
+
attr_reader :ripemd160
|
86
|
+
# caching getter for RIPEMD160 message digest.
|
87
|
+
def ripemd160
|
88
|
+
@ripemd160 = self.class.ripemd160(path) unless @ripemd160
|
89
|
+
@ripemd160
|
90
|
+
end
|
91
|
+
# getter for RIPEMD160 message digest.
|
92
|
+
# This getter forces the digest to be reloaded.
|
93
|
+
def ripemd160!
|
94
|
+
@ripemd160 = nil
|
95
|
+
ripemd160
|
96
|
+
end
|
97
|
+
|
98
|
+
# SHA message digest.
|
99
|
+
attr_reader :sha
|
100
|
+
# caching getter for SHA message digest.
|
101
|
+
def sha
|
102
|
+
@sha = self.class.sha(path) unless @sha
|
103
|
+
@sha
|
104
|
+
end
|
105
|
+
# getter for SHA message digest.
|
106
|
+
# This getter forces the digest to be reloaded.
|
107
|
+
def sha!
|
108
|
+
@sha = nil
|
109
|
+
sha
|
110
|
+
end
|
111
|
+
|
112
|
+
# SHA1 message digest.
|
113
|
+
attr_reader :sha1
|
114
|
+
# caching getter for SHA1 message digest.
|
115
|
+
def sha1
|
116
|
+
@sha1 = self.class.sha1(path) unless @sha1
|
117
|
+
@sha1
|
118
|
+
end
|
119
|
+
# getter for SHA1 message digest.
|
120
|
+
# This getter forces the digest to be reloaded.
|
121
|
+
def sha1!
|
122
|
+
@sha1 = nil
|
123
|
+
sha1
|
124
|
+
end
|
125
|
+
|
126
|
+
# SHA224 message digest.
|
127
|
+
attr_reader :sha224
|
128
|
+
# caching getter for SHA224 message digest.
|
129
|
+
def sha224
|
130
|
+
@sha224 = self.class.sha224(path) unless @sha224
|
131
|
+
@sha224
|
132
|
+
end
|
133
|
+
# getter for SHA224 message digest.
|
134
|
+
# This getter forces the digest to be reloaded.
|
135
|
+
def sha224!
|
136
|
+
@sha224 = nil
|
137
|
+
sha224
|
138
|
+
end
|
139
|
+
|
140
|
+
# SHA256 message digest.
|
141
|
+
attr_reader :sha256
|
142
|
+
# caching getter for SHA256 message digest.
|
143
|
+
def sha256
|
144
|
+
@sha256 = self.class.sha256(path) unless @sha256
|
145
|
+
@sha256
|
146
|
+
end
|
147
|
+
# getter for SHA256 message digest.
|
148
|
+
# This getter forces the digest to be reloaded.
|
149
|
+
def sha256!
|
150
|
+
@sha256 = nil
|
151
|
+
sha256
|
152
|
+
end
|
153
|
+
|
154
|
+
# SHA384 message digest.
|
155
|
+
attr_reader :sha384
|
156
|
+
# caching getter for SHA384 message digest.
|
157
|
+
def sha384
|
158
|
+
@sha384 = self.class.sha384(path) unless @sha384
|
159
|
+
@sha384
|
160
|
+
end
|
161
|
+
# getter for SHA384 message digest.
|
162
|
+
# This getter forces the digest to be reloaded.
|
163
|
+
def sha384!
|
164
|
+
@sha384 = nil
|
165
|
+
sha384
|
166
|
+
end
|
167
|
+
|
168
|
+
# SHA512 message digest.
|
169
|
+
attr_reader :sha512
|
170
|
+
# caching getter for SHA512 message digest.
|
171
|
+
def sha512
|
172
|
+
@sha512 = self.class.sha512(path) unless @sha512
|
173
|
+
@sha512
|
174
|
+
end
|
175
|
+
# getter for SHA512 message digest.
|
176
|
+
# This getter forces the digest to be reloaded.
|
177
|
+
def sha512!
|
178
|
+
@sha512 = nil
|
179
|
+
sha512
|
180
|
+
end
|
181
|
+
|
182
|
+
# refresh the Richfile added attributes.
|
183
|
+
# All the attributes referred once are loaded.
|
184
|
+
def refresh_digests!
|
185
|
+
Richfile::Digests::each_digest_symbols do |d_bang, d_var|
|
186
|
+
send d_bang if (instance_variable_get(d_var))
|
187
|
+
end
|
188
|
+
self
|
189
|
+
end
|
190
|
+
# refresh all attributes.
|
191
|
+
# All attributes wil be loaded, so all digests will be calculated.
|
192
|
+
# You will most probably never need this method.
|
193
|
+
def refresh_all_digests!
|
194
|
+
Richfile::Digests::each_digest_symbols do |d_bang, d_var|
|
195
|
+
send d_bang
|
196
|
+
end
|
197
|
+
self
|
198
|
+
end
|
199
|
+
end#InstanceMethods
|
200
|
+
|
201
|
+
# Digest-related methods to be included into File class.
|
202
|
+
module ClassMethods
|
203
|
+
# compute the DSS1 digest of a file.
|
204
|
+
def dss1(path)
|
205
|
+
hexdigest('DSS1', path)
|
206
|
+
end
|
207
|
+
# compute the DSS1 digest of a file.
|
208
|
+
# uses digest with 'DSS1' as digest to be used.
|
209
|
+
def md2(path)
|
210
|
+
hexdigest('MD2', path)
|
211
|
+
end
|
212
|
+
# compute the MD4 digest of a file.
|
213
|
+
# uses digest with 'MD4' as digest to be used.
|
214
|
+
def md4(path)
|
215
|
+
hexdigest('MD4', path)
|
216
|
+
end
|
217
|
+
# compute the MD5 digest of a file.
|
218
|
+
# uses digest with 'MD5' as digest to be used.
|
219
|
+
def md5(path)
|
220
|
+
hexdigest('MD5', path)
|
221
|
+
end
|
222
|
+
# compute the RIPEMD160 digest of a file.
|
223
|
+
# uses digest with 'RIPEMD160' as digest to be used.
|
224
|
+
def ripemd160(path)
|
225
|
+
hexdigest('RIPEMD160', path)
|
226
|
+
end
|
227
|
+
# compute the SHA digest of a file.
|
228
|
+
# uses digest with 'SHA' as digest to be used.
|
229
|
+
def sha(path)
|
230
|
+
hexdigest('SHA', path)
|
231
|
+
end
|
232
|
+
# compute the SHA1 digest of a file.
|
233
|
+
# uses digest with 'SHA1' as digest to be used.
|
234
|
+
def sha1(path)
|
235
|
+
hexdigest('SHA1', path)
|
236
|
+
end
|
237
|
+
# compute the SHA224 digest of a file.
|
238
|
+
# uses digest with 'SHA224' as digest to be used.
|
239
|
+
def sha224(path)
|
240
|
+
hexdigest('SHA224', path)
|
241
|
+
end
|
242
|
+
# compute the SHA256 digest of a file.
|
243
|
+
# uses digest with 'SHA256' as digest to be used.
|
244
|
+
def sha256(path)
|
245
|
+
hexdigest('SHA256', path)
|
246
|
+
end
|
247
|
+
# compute the SHA384 digest of a file.
|
248
|
+
# uses digest with 'SHA384' as digest to be used.
|
249
|
+
def sha384(path)
|
250
|
+
hexdigest('SHA384', path)
|
251
|
+
end
|
252
|
+
# compute the SHA512 digest of a file.
|
253
|
+
# uses digest with 'SHA512' as digest to be used.
|
254
|
+
def sha512(path)
|
255
|
+
hexdigest('SHA512', path)
|
256
|
+
end
|
257
|
+
|
258
|
+
# compute a digest for a given file.
|
259
|
+
# - digest: the OpenSSL digest name
|
260
|
+
# - path: the file path
|
261
|
+
# - returns: hexdigest of the content of the file at the given path
|
262
|
+
def hexdigest(digest, path)
|
263
|
+
File.open(path, 'r') do |f|
|
264
|
+
d = OpenSSL::Digest.new(digest)
|
265
|
+
d << f.read
|
266
|
+
d.hexdigest
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end#DigestClassmethods
|
270
|
+
|
271
|
+
module Base #:nodoc:
|
272
|
+
def self.included(mod) #:nodoc:
|
273
|
+
mod.extend(Richfile::Digests::ClassMethods)
|
274
|
+
mod.class_eval { include(Richfile::Digests::InstanceMethods) }
|
275
|
+
end
|
276
|
+
end#Base
|
277
|
+
|
278
|
+
end#Digests
|
279
|
+
|
280
|
+
end#Richfile
|
@@ -0,0 +1,54 @@
|
|
1
|
+
#require 'mime/types'
|
2
|
+
|
3
|
+
module Richfile
|
4
|
+
|
5
|
+
# Mimetype functionality for attributes for File objects.
|
6
|
+
# Currently, this works only for Unix-like OS, since it uses the file system
|
7
|
+
# utility.
|
8
|
+
module Mimetype
|
9
|
+
|
10
|
+
# Methods made available for instances.
|
11
|
+
module InstanceMethods
|
12
|
+
# the MIME type.
|
13
|
+
attr_reader :mimetype
|
14
|
+
# get the MIME type.
|
15
|
+
def mimetype
|
16
|
+
@mimetype = self.class.mimetype(path) unless @mimetype
|
17
|
+
@mimetype
|
18
|
+
end
|
19
|
+
# re-fetch the MIME type.
|
20
|
+
def mimetype!
|
21
|
+
@mimetype = nil
|
22
|
+
self.mimetype
|
23
|
+
end
|
24
|
+
end#InstanceMethods
|
25
|
+
|
26
|
+
# Methods implanted into the File class itself.
|
27
|
+
module ClassMethods
|
28
|
+
# get the MIME type from a file using Richfile::Mimetype.mimetype_using_file.
|
29
|
+
def mimetype(path)
|
30
|
+
Richfile::Mimetype.mimetype_using_file(path).first
|
31
|
+
end
|
32
|
+
end#ClassMethods
|
33
|
+
|
34
|
+
# determinate the MimeType using the file system utility.
|
35
|
+
# This is probably only available on Unix-like systems, but is usually
|
36
|
+
# quite reliable.
|
37
|
+
#
|
38
|
+
# - path: the full path of the file
|
39
|
+
# - returns: the mimetype string
|
40
|
+
def self.mimetype_using_file(path)
|
41
|
+
mimestring = `file --mime -b "#{path}"`.gsub(/\n/,"")
|
42
|
+
mimetype, encoding = /(\w+\/\w+); (.+)/.match(mimestring)[1,2]
|
43
|
+
return mimetype, encoding
|
44
|
+
end
|
45
|
+
|
46
|
+
module Base #:nodoc:
|
47
|
+
def self.included(mod) #:nodoc:
|
48
|
+
mod.extend(Richfile::Mimetype::ClassMethods)
|
49
|
+
mod.class_eval { include(Richfile::Mimetype::InstanceMethods) }
|
50
|
+
end
|
51
|
+
end#Base
|
52
|
+
|
53
|
+
end#Mimetype
|
54
|
+
end#Richfile
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tsalzer-richfile
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Till Salzer
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-04-02 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -26,6 +26,8 @@ files:
|
|
26
26
|
- VERSION.yml
|
27
27
|
- lib/richfile
|
28
28
|
- lib/richfile/base.rb
|
29
|
+
- lib/richfile/digests.rb
|
30
|
+
- lib/richfile/mimetype.rb
|
29
31
|
- lib/richfile.rb
|
30
32
|
has_rdoc: true
|
31
33
|
homepage: http://github.com/tsalzer/richfile
|