richfile 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +51 -0
- data/VERSION.yml +4 -0
- data/lib/richfile.rb +4 -0
- data/lib/richfile/base.rb +55 -0
- data/lib/richfile/digests.rb +280 -0
- data/lib/richfile/mimetype.rb +54 -0
- metadata +61 -0
data/README.rdoc
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
= Richfile
|
2
|
+
|
3
|
+
A simple gem which adds some additional methods to File objects.
|
4
|
+
|
5
|
+
== Install
|
6
|
+
|
7
|
+
gem install tsalzer-richfile --source http://gems.github.com
|
8
|
+
|
9
|
+
|
10
|
+
== What is Richfile?
|
11
|
+
|
12
|
+
Richfile extends the Ruby built-in File instances with some sometimes
|
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)
|
16
|
+
|
17
|
+
Note that there is no built-in magic to keep the once-fetched attributes
|
18
|
+
in sync with the effective attributes of the real files.
|
19
|
+
|
20
|
+
== Usage
|
21
|
+
|
22
|
+
You simple require richfile:
|
23
|
+
|
24
|
+
require 'richfile'
|
25
|
+
|
26
|
+
Now, every new File object has a list of additional attributes. Whenever you
|
27
|
+
access the attributes the first time, the data is pulled from the file system
|
28
|
+
and cached in the File object.
|
29
|
+
|
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
|
32
|
+
attributes. When you are just interested in a single attribute, call the
|
33
|
+
attribute with an added bang (like <code>size!</code>).
|
34
|
+
|
35
|
+
== Building a new Gem
|
36
|
+
|
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
|
40
|
+
|
41
|
+
rake gemspec
|
42
|
+
gem build richfile.gemspec
|
43
|
+
|
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
|
47
|
+
|
48
|
+
== License
|
49
|
+
|
50
|
+
The richfile gem comes to you under the MIT License. You should find the
|
51
|
+
license text in the file MIT-LICENSE in the gem folder.
|
data/VERSION.yml
ADDED
data/lib/richfile.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# Extension to File.
|
2
|
+
module Richfile
|
3
|
+
|
4
|
+
# Methods to be included in File objects.
|
5
|
+
module Base
|
6
|
+
# size of the file in bytes.
|
7
|
+
attr_reader :size
|
8
|
+
|
9
|
+
# refresh the Richfile added attributes.
|
10
|
+
# All the attributes referred once are loaded.
|
11
|
+
def refresh!
|
12
|
+
self.size! if @size
|
13
|
+
refresh_digests! if respond_to?(:refresh_all_digests!)
|
14
|
+
self.mimetype! if @mimetype
|
15
|
+
self
|
16
|
+
end
|
17
|
+
|
18
|
+
# refresh all attributes.
|
19
|
+
# All attributes wil be loaded, so all digests will be calculated.
|
20
|
+
# You will most probably never need this method.
|
21
|
+
def refresh_all!
|
22
|
+
self.size!
|
23
|
+
refresh_all_digests! if respond_to?(:refresh_all_digests!)
|
24
|
+
self.mimetype!
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
# proxies File.exists?.
|
29
|
+
# This will always go to the real File.exists?, it will not be cached.
|
30
|
+
def exists?
|
31
|
+
File.exists?(path)
|
32
|
+
end
|
33
|
+
|
34
|
+
# size of the file in bytes.
|
35
|
+
# see File#size
|
36
|
+
def size
|
37
|
+
@size = File.size(self.path) unless @size
|
38
|
+
@size
|
39
|
+
end
|
40
|
+
# refresh the size attribute.
|
41
|
+
def size!
|
42
|
+
@size = nil
|
43
|
+
self.size
|
44
|
+
end
|
45
|
+
|
46
|
+
end#Base
|
47
|
+
|
48
|
+
# include the Richfile::Base module into the File class.
|
49
|
+
def self.install
|
50
|
+
File.send :include, Richfile::Base
|
51
|
+
File.send :include, Richfile::Digests::Base
|
52
|
+
File.send :include, Richfile::Mimetype::Base
|
53
|
+
end
|
54
|
+
|
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
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: richfile
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Till Salzer
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-04-02 00:00:00 +02:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Extends Ruby File objects with some rich instance attributes.
|
17
|
+
email: till.salzer@googlemail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README.rdoc
|
24
|
+
files:
|
25
|
+
- README.rdoc
|
26
|
+
- VERSION.yml
|
27
|
+
- lib/richfile/base.rb
|
28
|
+
- lib/richfile/digests.rb
|
29
|
+
- lib/richfile/mimetype.rb
|
30
|
+
- lib/richfile.rb
|
31
|
+
has_rdoc: true
|
32
|
+
homepage: http://github.com/tsalzer/richfile
|
33
|
+
licenses: []
|
34
|
+
|
35
|
+
post_install_message:
|
36
|
+
rdoc_options:
|
37
|
+
- --inline-source
|
38
|
+
- --charset=UTF-8
|
39
|
+
require_paths:
|
40
|
+
- lib
|
41
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: "0"
|
46
|
+
version:
|
47
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: "0"
|
52
|
+
version:
|
53
|
+
requirements: []
|
54
|
+
|
55
|
+
rubyforge_project:
|
56
|
+
rubygems_version: 1.3.4
|
57
|
+
signing_key:
|
58
|
+
specification_version: 2
|
59
|
+
summary: More attributes for Ruby File
|
60
|
+
test_files: []
|
61
|
+
|