mini_exiftool 1.0.2 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Changelog +5 -1
- data/lib/mini_exiftool.rb +4 -3
- data/test/data/test 36/"Bench.jpg +0 -0
- data/test/test_class_methods.rb +0 -8
- data/test/test_dumping.rb +0 -10
- data/test/test_escape_filename.rb +25 -0
- data/test/test_read.rb +1 -1
- data/test/test_read_numerical.rb +1 -1
- data/test/test_save.rb +1 -1
- metadata +6 -5
- data/lib/mini_exiftool.new.rb +0 -445
- data/x.rb +0 -3
data/Changelog
CHANGED
@@ -1,6 +1,10 @@
|
|
1
|
+
Version 1.1.0
|
2
|
+
- Escaping filenames in shell commands
|
3
|
+
Thanks to Michael Hoy for the hint and implementing a patch which was
|
4
|
+
the base for this fix.
|
1
5
|
Version 1.0.2
|
2
6
|
- Fixing warings
|
3
|
-
|
7
|
+
Thanks to Peter-Hinrich Krogmann for the hint.
|
4
8
|
Version 1.0.1
|
5
9
|
- Fixing bug [#22726]
|
6
10
|
Making MiniExiftool::Error public.
|
data/lib/mini_exiftool.rb
CHANGED
@@ -16,6 +16,7 @@ require 'fileutils'
|
|
16
16
|
require 'tempfile'
|
17
17
|
require 'pstore'
|
18
18
|
require 'set'
|
19
|
+
require 'shellwords'
|
19
20
|
|
20
21
|
# Simple OO access to the Exiftool command-line application.
|
21
22
|
class MiniExiftool
|
@@ -29,7 +30,7 @@ class MiniExiftool
|
|
29
30
|
attr_reader :filename
|
30
31
|
attr_accessor :numerical, :composite, :convert_encoding, :errors, :timestamps
|
31
32
|
|
32
|
-
VERSION = '1.0
|
33
|
+
VERSION = '1.1.0'
|
33
34
|
|
34
35
|
# +opts+ support at the moment
|
35
36
|
# * <code>:numerical</code> for numerical values, default is +false+
|
@@ -80,7 +81,7 @@ class MiniExiftool
|
|
80
81
|
opt_params << (@numerical ? '-n ' : '')
|
81
82
|
opt_params << (@composite ? '' : '-e ')
|
82
83
|
opt_params << (@convert_encoding ? '-L ' : '')
|
83
|
-
cmd = %Q(#@@cmd -q -q -s -t #{opt_params} #{@@sep_op}
|
84
|
+
cmd = %Q(#@@cmd -q -q -s -t #{opt_params} #{@@sep_op} #{Shellwords.escape(filename)})
|
84
85
|
if run(cmd)
|
85
86
|
parse_output
|
86
87
|
else
|
@@ -156,7 +157,7 @@ class MiniExiftool
|
|
156
157
|
opt_params = ''
|
157
158
|
opt_params << (arr_val.detect {|x| x.kind_of?(Numeric)} ? '-n ' : '')
|
158
159
|
opt_params << (@convert_encoding ? '-L ' : '')
|
159
|
-
cmd = %Q(#@@cmd -q -P -overwrite_original #{opt_params} #{tag_params}
|
160
|
+
cmd = %Q(#@@cmd -q -P -overwrite_original #{opt_params} #{tag_params} #{temp_filename})
|
160
161
|
result = run(cmd)
|
161
162
|
unless result
|
162
163
|
all_ok = false
|
Binary file
|
data/test/test_class_methods.rb
CHANGED
@@ -27,14 +27,6 @@ class TestClassMethods < TestCase
|
|
27
27
|
rescue MiniExiftool::Error => e
|
28
28
|
assert_match /File 'not_existing_file' does not exist/, e.message
|
29
29
|
end
|
30
|
-
assert_raises MiniExiftool::Error do
|
31
|
-
MiniExiftool.new __FILE__ # file type wich Exiftool can not handle
|
32
|
-
end
|
33
|
-
begin
|
34
|
-
MiniExiftool.new __FILE__ # file type wich Exiftool can not handle
|
35
|
-
rescue MiniExiftool::Error => e
|
36
|
-
assert_match /Error: Unknown (?:image|file) type/, e.message
|
37
|
-
end
|
38
30
|
end
|
39
31
|
|
40
32
|
def test_command
|
data/test/test_dumping.rb
CHANGED
@@ -76,14 +76,4 @@ class TestDumping < TestCase
|
|
76
76
|
assert_equal true, MiniExiftool.from_yaml(numerical.to_yaml).numerical
|
77
77
|
end
|
78
78
|
|
79
|
-
def test_heuristics_for_restoring_timestamps
|
80
|
-
standard = @mini_exiftool.to_hash
|
81
|
-
timestamps = MiniExiftool.new(@filename_test, :timestamps => DateTime).to_hash
|
82
|
-
assert_equal Time, MiniExiftool.from_hash(standard).timestamps
|
83
|
-
assert_equal DateTime, MiniExiftool.from_hash(timestamps).timestamps
|
84
|
-
# Doesn't work yet.
|
85
|
-
# assert_equal Time, MiniExiftool.from_yaml(standard.to_yaml).timestamps
|
86
|
-
# assert_equal DateTime, MiniExiftool.from_yaml(timestamps.to_yaml).timestamps
|
87
|
-
end
|
88
|
-
|
89
79
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'helpers_for_test'
|
2
|
+
|
3
|
+
class TestEscapeFilename < TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@temp_file = Tempfile.new('test')
|
7
|
+
@temp_file.close
|
8
|
+
@temp_filename = @temp_file.path
|
9
|
+
@org_filename = File.dirname(__FILE__) + '/data/test 36"Bench.jpg'
|
10
|
+
FileUtils.cp(@org_filename, @temp_filename)
|
11
|
+
@mini_exiftool = MiniExiftool.new @temp_filename
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_access
|
15
|
+
assert_equal '36" Bench', @mini_exiftool['description']
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_save
|
19
|
+
desc = 'another bench'
|
20
|
+
@mini_exiftool.description = desc
|
21
|
+
assert @mini_exiftool.save
|
22
|
+
assert_equal desc, @mini_exiftool.description
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
data/test/test_read.rb
CHANGED
@@ -25,7 +25,7 @@ class TestRead < TestCase
|
|
25
25
|
assert_kind_of Float, @mini_exiftool['MaxApertureValue']
|
26
26
|
assert_kind_of String, @mini_exiftool.flash
|
27
27
|
assert_kind_of Fixnum, @mini_exiftool['ExposureCompensation']
|
28
|
-
assert_kind_of String, @mini_exiftool['SubjectLocation']
|
28
|
+
assert_kind_of String, (@mini_exiftool['SubjectLocation'] || @mini_exiftool['SubjectArea'])
|
29
29
|
assert_kind_of Array, @mini_exiftool['Keywords']
|
30
30
|
assert_kind_of String, @mini_exiftool['SupplementalCategories']
|
31
31
|
assert_kind_of Array, @mini_exiftool['SupplementalCategories'].to_a
|
data/test/test_read_numerical.rb
CHANGED
@@ -22,7 +22,7 @@ class TestReadNumerical < TestCase
|
|
22
22
|
assert_kind_of Fixnum, @mini_exiftool_num.flash
|
23
23
|
assert_kind_of String, @mini_exiftool_num.exif_version
|
24
24
|
assert_kind_of Fixnum, @mini_exiftool_num['ExposureCompensation']
|
25
|
-
assert_kind_of String, @mini_exiftool_num['SubjectLocation']
|
25
|
+
assert_kind_of String, (@mini_exiftool_num['SubjectLocation'] || @mini_exiftool_num['SubjectArea'])
|
26
26
|
assert_kind_of Array, @mini_exiftool_num['Keywords']
|
27
27
|
assert_kind_of String, @mini_exiftool_num['SupplementalCategories']
|
28
28
|
assert_kind_of Array, @mini_exiftool_num['SupplementalCategories'].to_a
|
data/test/test_save.rb
CHANGED
@@ -32,7 +32,7 @@ class TestSave < TestCase
|
|
32
32
|
result = @mini_exiftool.save
|
33
33
|
assert_equal false, result
|
34
34
|
assert_equal 1, @mini_exiftool.errors.size
|
35
|
-
|
35
|
+
assert_match(/Can't convert IFD0:Orientation \(not in PrintConv\)/,
|
36
36
|
@mini_exiftool.errors['Orientation'])
|
37
37
|
assert @mini_exiftool.changed?
|
38
38
|
assert @mini_exiftool.changed_tags.include?('Orientation')
|
metadata
CHANGED
@@ -5,9 +5,9 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
+
- 1
|
8
9
|
- 0
|
9
|
-
|
10
|
-
version: 1.0.2
|
10
|
+
version: 1.1.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jan Friedrich
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date:
|
18
|
+
date: 2011-02-10 00:00:00 +01:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|
@@ -32,25 +32,25 @@ files:
|
|
32
32
|
- examples/external_photo.rb
|
33
33
|
- examples/print_portraits.rb
|
34
34
|
- examples/shift_time.rb
|
35
|
-
- lib/mini_exiftool.new.rb
|
36
35
|
- lib/mini_exiftool.rb
|
37
36
|
- setup.rb
|
38
37
|
- test/helpers_for_test.rb
|
39
38
|
- test/test_class_methods.rb
|
40
39
|
- test/test_composite.rb
|
41
40
|
- test/test_dumping.rb
|
41
|
+
- test/test_escape_filename.rb
|
42
42
|
- test/test_read.rb
|
43
43
|
- test/test_read_numerical.rb
|
44
44
|
- test/test_save.rb
|
45
45
|
- test/test_special.rb
|
46
46
|
- test/test_special_dates.rb
|
47
47
|
- test/test_write.rb
|
48
|
-
- x.rb
|
49
48
|
- Rakefile
|
50
49
|
- COPYING
|
51
50
|
- Changelog
|
52
51
|
- test/data/Canon.jpg
|
53
52
|
- test/data/INFORMATION
|
53
|
+
- test/data/test 36"Bench.jpg
|
54
54
|
- test/data/test.jpg
|
55
55
|
- test/data/test_special_dates.jpg
|
56
56
|
- README
|
@@ -96,6 +96,7 @@ test_files:
|
|
96
96
|
- test/test_class_methods.rb
|
97
97
|
- test/test_composite.rb
|
98
98
|
- test/test_dumping.rb
|
99
|
+
- test/test_escape_filename.rb
|
99
100
|
- test/test_read.rb
|
100
101
|
- test/test_read_numerical.rb
|
101
102
|
- test/test_save.rb
|
data/lib/mini_exiftool.new.rb
DELETED
@@ -1,445 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# MiniExiftool
|
3
|
-
#
|
4
|
-
# This library is wrapper for the Exiftool command-line
|
5
|
-
# application (http://www.sno.phy.queensu.ca/~phil/exiftool/)
|
6
|
-
# written by Phil Harvey.
|
7
|
-
# Read and write access is done in a clean OO manner.
|
8
|
-
#
|
9
|
-
# Author: Jan Friedrich
|
10
|
-
# Copyright (c) 2007, 2008 by Jan Friedrich
|
11
|
-
# Licensed under the GNU LESSER GENERAL PUBLIC LICENSE,
|
12
|
-
# Version 2.1, February 1999
|
13
|
-
#
|
14
|
-
|
15
|
-
require 'fileutils'
|
16
|
-
require 'tempfile'
|
17
|
-
require 'pstore'
|
18
|
-
require 'set'
|
19
|
-
|
20
|
-
# Simple OO access to the Exiftool command-line application.
|
21
|
-
class MiniExiftool
|
22
|
-
|
23
|
-
# Name of the Exiftool command-line application
|
24
|
-
@@cmd = 'exiftool'
|
25
|
-
|
26
|
-
# Hash of the standard options used when call MiniExiftool.new
|
27
|
-
@@opts = { :numerical => false, :composite => true, :convert_encoding => false, :timestamps => Time }
|
28
|
-
|
29
|
-
attr_reader :filename
|
30
|
-
attr_accessor :numerical, :composite, :convert_encoding, :errors, :timestamps
|
31
|
-
|
32
|
-
VERSION = '1.0.1'
|
33
|
-
|
34
|
-
# +opts+ support at the moment
|
35
|
-
# * <code>:numerical</code> for numerical values, default is +false+
|
36
|
-
# * <code>:composite</code> for including composite tags while loading,
|
37
|
-
# default is +true+
|
38
|
-
# * <code>:convert_encoding</code> convert encoding (See -L-option of
|
39
|
-
# the exiftool command-line application, default is +false+
|
40
|
-
# * <code>:timestamps</code> generating DateTime objects instead of
|
41
|
-
# Time objects if set to <code>DateTime</code>, default is +Time+
|
42
|
-
#
|
43
|
-
# <b>ATTENTION:</b> Time objects are created using <code>Time.local</code>
|
44
|
-
# therefore they use <em>your local timezone</em>, DateTime objects instead
|
45
|
-
# are created <em>without timezone</em>!
|
46
|
-
def initialize filename=nil, opts={}
|
47
|
-
opts = @@opts.merge opts
|
48
|
-
@numerical = opts[:numerical]
|
49
|
-
@composite = opts[:composite]
|
50
|
-
@convert_encoding = opts[:convert_encoding]
|
51
|
-
@timestamps = opts[:timestamps]
|
52
|
-
@values = TagHash.new
|
53
|
-
@tag_names = TagHash.new
|
54
|
-
@changed_values = TagHash.new
|
55
|
-
@errors = TagHash.new
|
56
|
-
load filename unless filename.nil?
|
57
|
-
end
|
58
|
-
|
59
|
-
def initialize_from_hash hash # :nodoc:
|
60
|
-
hash.each_pair do |tag,value|
|
61
|
-
set_value tag, value
|
62
|
-
end
|
63
|
-
set_attributes_by_heuristic
|
64
|
-
self
|
65
|
-
end
|
66
|
-
|
67
|
-
# Load the tags of filename.
|
68
|
-
def load filename
|
69
|
-
unless filename && File.exist?(filename)
|
70
|
-
raise MiniExiftool::Error.new("File '#{filename}' does not exist.")
|
71
|
-
end
|
72
|
-
if File.directory?(filename)
|
73
|
-
raise MiniExiftool::Error.new("'#{filename}' is a directory.")
|
74
|
-
end
|
75
|
-
@filename = filename
|
76
|
-
@values.clear
|
77
|
-
@tag_names.clear
|
78
|
-
@changed_values.clear
|
79
|
-
opt_params = ''
|
80
|
-
opt_params << (@numerical ? '-n ' : '')
|
81
|
-
opt_params << (@composite ? '' : '-e ')
|
82
|
-
opt_params << (@convert_encoding ? '-L ' : '')
|
83
|
-
cmd = %Q(#@@cmd -q -q -s -t #{opt_params} #{@@sep_op} "#{filename}")
|
84
|
-
if run(cmd)
|
85
|
-
parse_output
|
86
|
-
else
|
87
|
-
raise MiniExiftool::Error.new(@error_text)
|
88
|
-
end
|
89
|
-
self
|
90
|
-
end
|
91
|
-
|
92
|
-
# Reload the tags of an already readed file.
|
93
|
-
def reload
|
94
|
-
load @filename
|
95
|
-
end
|
96
|
-
|
97
|
-
# Returns the value of a tag.
|
98
|
-
def [] tag
|
99
|
-
@changed_values[tag] || @values[tag]
|
100
|
-
end
|
101
|
-
|
102
|
-
# Set the value of a tag.
|
103
|
-
def []=(tag, val)
|
104
|
-
@changed_values[tag] = val
|
105
|
-
end
|
106
|
-
|
107
|
-
# Returns true if any tag value is changed or if the value of a
|
108
|
-
# given tag is changed.
|
109
|
-
def changed? tag=false
|
110
|
-
if tag
|
111
|
-
@changed_values.include? tag
|
112
|
-
else
|
113
|
-
!@changed_values.empty?
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
# Revert all changes or the change of a given tag.
|
118
|
-
def revert tag=nil
|
119
|
-
if tag
|
120
|
-
val = @changed_values.delete(tag)
|
121
|
-
res = val != nil
|
122
|
-
else
|
123
|
-
res = @changed_values.size > 0
|
124
|
-
@changed_values.clear
|
125
|
-
end
|
126
|
-
res
|
127
|
-
end
|
128
|
-
|
129
|
-
# Returns an array of the tags (original tag names) of the readed file.
|
130
|
-
def tags
|
131
|
-
@values.keys.map { |key| @tag_names[key] }
|
132
|
-
end
|
133
|
-
|
134
|
-
# Returns an array of all changed tags.
|
135
|
-
def changed_tags
|
136
|
-
@changed_values.keys.map { |key| MiniExiftool.original_tag(key) }
|
137
|
-
end
|
138
|
-
|
139
|
-
# Save the changes to the file.
|
140
|
-
def save
|
141
|
-
return false if @changed_values.empty?
|
142
|
-
@errors.clear
|
143
|
-
temp_file = Tempfile.new('mini_exiftool')
|
144
|
-
temp_file.close
|
145
|
-
temp_filename = temp_file.path
|
146
|
-
FileUtils.cp filename, temp_filename
|
147
|
-
all_ok = true
|
148
|
-
@changed_values.each do |tag, val|
|
149
|
-
original_tag = MiniExiftool.original_tag(tag)
|
150
|
-
arr_val = val.kind_of?(Array) ? val : [val]
|
151
|
-
arr_val.map! {|e| convert e}
|
152
|
-
tag_params = ''
|
153
|
-
arr_val.each do |v|
|
154
|
-
tag_params << %Q(-#{original_tag}="#{v}" )
|
155
|
-
end
|
156
|
-
opt_params = ''
|
157
|
-
opt_params << (arr_val.detect {|x| x.kind_of?(Numeric)} ? '-n ' : '')
|
158
|
-
opt_params << (@convert_encoding ? '-L ' : '')
|
159
|
-
cmd = %Q(#@@cmd -q -P -overwrite_original #{opt_params} #{tag_params} "#{temp_filename}")
|
160
|
-
result = run(cmd)
|
161
|
-
unless result
|
162
|
-
all_ok = false
|
163
|
-
@errors[tag] = @error_text.gsub(/Nothing to do.\n\z/, '').chomp
|
164
|
-
end
|
165
|
-
end
|
166
|
-
if all_ok
|
167
|
-
FileUtils.cp temp_filename, filename
|
168
|
-
reload
|
169
|
-
end
|
170
|
-
temp_file.delete
|
171
|
-
all_ok
|
172
|
-
end
|
173
|
-
|
174
|
-
# Returns a hash of the original loaded values of the MiniExiftool
|
175
|
-
# instance.
|
176
|
-
def to_hash
|
177
|
-
result = {}
|
178
|
-
@values.each do |k,v|
|
179
|
-
result[@tag_names[k]] = v
|
180
|
-
end
|
181
|
-
result
|
182
|
-
end
|
183
|
-
|
184
|
-
# Returns a YAML representation of the original loaded values of the
|
185
|
-
# MiniExiftool instance.
|
186
|
-
def to_yaml
|
187
|
-
to_hash.to_yaml
|
188
|
-
end
|
189
|
-
|
190
|
-
# Create a MiniExiftool instance from a hash
|
191
|
-
def self.from_hash hash
|
192
|
-
instance = MiniExiftool.new
|
193
|
-
instance.initialize_from_hash hash
|
194
|
-
instance
|
195
|
-
end
|
196
|
-
|
197
|
-
# Create a MiniExiftool instance from YAML data created with
|
198
|
-
# MiniExiftool#to_yaml
|
199
|
-
def self.from_yaml yaml
|
200
|
-
MiniExiftool.from_hash YAML.load(yaml)
|
201
|
-
end
|
202
|
-
|
203
|
-
# Returns the command name of the called Exiftool application.
|
204
|
-
def self.command
|
205
|
-
@@cmd
|
206
|
-
end
|
207
|
-
|
208
|
-
# Setting the command name of the called Exiftool application.
|
209
|
-
def self.command= cmd
|
210
|
-
@@cmd = cmd
|
211
|
-
end
|
212
|
-
|
213
|
-
# Returns the options hash.
|
214
|
-
def self.opts
|
215
|
-
@@opts
|
216
|
-
end
|
217
|
-
|
218
|
-
# Returns a set of all known tags of Exiftool.
|
219
|
-
def self.all_tags
|
220
|
-
unless defined? @@all_tags
|
221
|
-
@@all_tags = pstore_get :all_tags
|
222
|
-
end
|
223
|
-
@@all_tags
|
224
|
-
end
|
225
|
-
|
226
|
-
# Returns a set of all possible writable tags of Exiftool.
|
227
|
-
def self.writable_tags
|
228
|
-
unless defined? @@writable_tags
|
229
|
-
@@writable_tags = pstore_get :writable_tags
|
230
|
-
end
|
231
|
-
@@writable_tags
|
232
|
-
end
|
233
|
-
|
234
|
-
# Returns the original Exiftool name of the given tag
|
235
|
-
def self.original_tag tag
|
236
|
-
unless defined? @@all_tags_map
|
237
|
-
@@all_tags_map = pstore_get :all_tags_map
|
238
|
-
end
|
239
|
-
@@all_tags_map[tag]
|
240
|
-
end
|
241
|
-
|
242
|
-
# Returns the version of the Exiftool command-line application.
|
243
|
-
def self.exiftool_version
|
244
|
-
output = `#{MiniExiftool.command} -ver 2>&1`
|
245
|
-
unless $?.exitstatus == 0
|
246
|
-
raise MiniExiftool::Error.new("Command '#{MiniExiftool.command}' not found")
|
247
|
-
end
|
248
|
-
output.chomp!
|
249
|
-
end
|
250
|
-
|
251
|
-
def self.unify tag
|
252
|
-
tag.gsub(/[-_]/,'').downcase
|
253
|
-
end
|
254
|
-
|
255
|
-
# Exception class
|
256
|
-
class MiniExiftool::Error < StandardError; end
|
257
|
-
|
258
|
-
############################################################################
|
259
|
-
private
|
260
|
-
############################################################################
|
261
|
-
|
262
|
-
@@error_file = Tempfile.new 'errors'
|
263
|
-
@@error_file.close
|
264
|
-
|
265
|
-
if Float(exiftool_version) < 7.41
|
266
|
-
@@separator = ', '
|
267
|
-
@@sep_op = ''
|
268
|
-
else
|
269
|
-
@@separator = '@@'
|
270
|
-
@@sep_op = '-sep @@'
|
271
|
-
end
|
272
|
-
|
273
|
-
def run cmd
|
274
|
-
if $DEBUG
|
275
|
-
$stderr.puts cmd
|
276
|
-
end
|
277
|
-
@output = `#{cmd} 2>#{@@error_file.path}`
|
278
|
-
@status = $?
|
279
|
-
unless @status.exitstatus == 0
|
280
|
-
@error_text = File.readlines(@@error_file.path).join
|
281
|
-
return false
|
282
|
-
else
|
283
|
-
@error_text = ''
|
284
|
-
return true
|
285
|
-
end
|
286
|
-
end
|
287
|
-
|
288
|
-
def convert val
|
289
|
-
case val
|
290
|
-
when Time
|
291
|
-
val = val.strftime('%Y:%m:%d %H:%M:%S')
|
292
|
-
end
|
293
|
-
val
|
294
|
-
end
|
295
|
-
|
296
|
-
def method_missing symbol, *args
|
297
|
-
tag_name = symbol.id2name
|
298
|
-
if tag_name.sub!(/=$/, '')
|
299
|
-
self[tag_name] = args.first
|
300
|
-
else
|
301
|
-
self[tag_name]
|
302
|
-
end
|
303
|
-
end
|
304
|
-
|
305
|
-
def parse_output
|
306
|
-
@output.each_line do |line|
|
307
|
-
tag, value = parse_line line
|
308
|
-
set_value tag, value
|
309
|
-
end
|
310
|
-
end
|
311
|
-
|
312
|
-
def parse_line line
|
313
|
-
if line =~ /^([^\t]+)\t(.*)$/
|
314
|
-
tag, value = $1, $2
|
315
|
-
case value
|
316
|
-
when /^\d{4}:\d\d:\d\d \d\d:\d\d:\d\d$/
|
317
|
-
arr = value.split(/[: ]/) #Fixed by kro44 - add parentheses
|
318
|
-
arr.map! {|elem| elem.to_i}
|
319
|
-
begin
|
320
|
-
if @timestamps == Time
|
321
|
-
value = Time.local(*arr) #Fixed by kro44 - add parentheses
|
322
|
-
elsif @timestamps == DateTime
|
323
|
-
value = DateTime.strptime(value,'%Y:%m:%d %H:%M:%S')
|
324
|
-
else
|
325
|
-
raise MiniExiftool::Error.new("Value #@timestamps not allowed for option timestamps.")
|
326
|
-
end
|
327
|
-
rescue ArgumentError
|
328
|
-
value = false
|
329
|
-
end
|
330
|
-
when /^\d+\.\d+$/
|
331
|
-
value = value.to_f
|
332
|
-
when /^0+[1-9]+$/
|
333
|
-
# nothing => String
|
334
|
-
when /^-?\d+$/
|
335
|
-
value = value.to_i
|
336
|
-
when /^[\d ]+$/
|
337
|
-
# nothing => String
|
338
|
-
when /#{@@separator}/
|
339
|
-
value = value.split @@separator
|
340
|
-
end
|
341
|
-
else
|
342
|
-
raise MiniExiftool::Error.new("Malformed line #{line.inspect} of exiftool output.")
|
343
|
-
end
|
344
|
-
unless value.respond_to?('to_a')
|
345
|
-
class << value
|
346
|
-
def to_a
|
347
|
-
[self]
|
348
|
-
end
|
349
|
-
end
|
350
|
-
end
|
351
|
-
return [tag, value]
|
352
|
-
end
|
353
|
-
|
354
|
-
def set_value tag, value
|
355
|
-
@tag_names[tag] = tag
|
356
|
-
@values[tag] = value
|
357
|
-
end
|
358
|
-
|
359
|
-
def set_attributes_by_heuristic
|
360
|
-
self.composite = tags.include?('ImageSize') ? true : false
|
361
|
-
self.numerical = self.file_size.kind_of?(Integer) ? true : false
|
362
|
-
# TODO: Is there a heuristic to determine @convert_encoding?
|
363
|
-
self.timestamps = self.FileModifyDate.kind_of?(DateTime) ? DateTime : Time
|
364
|
-
end
|
365
|
-
|
366
|
-
def temp_filename
|
367
|
-
unless @temp_filename
|
368
|
-
temp_file = Tempfile.new('mini-exiftool')
|
369
|
-
temp_file.close
|
370
|
-
FileUtils.cp(@filename, temp_file.path)
|
371
|
-
@temp_filename = temp_file.path
|
372
|
-
end
|
373
|
-
@temp_filename
|
374
|
-
end
|
375
|
-
|
376
|
-
def self.pstore_get attribute
|
377
|
-
load_or_create_pstore unless defined? @@pstore
|
378
|
-
result = nil
|
379
|
-
@@pstore.transaction(true) do |ps|
|
380
|
-
result = ps[attribute]
|
381
|
-
end
|
382
|
-
result
|
383
|
-
end
|
384
|
-
|
385
|
-
def self.load_or_create_pstore
|
386
|
-
# This will hopefully work on *NIX and Windows systems
|
387
|
-
home = ENV['HOME'] || ENV['HOMEDRIVE'] + ENV['HOMEPATH'] || ENV['USERPROFILE']
|
388
|
-
subdir = RUBY_PLATFORM =~ /win/i ? '_mini_exiftool' : '.mini_exiftool'
|
389
|
-
FileUtils.mkdir_p(File.join(home, subdir))
|
390
|
-
filename = File.join(home, subdir, 'exiftool_tags_' << exiftool_version.gsub('.', '_') << '.pstore')
|
391
|
-
@@pstore = PStore.new filename
|
392
|
-
if !File.exist?(filename) || File.size(filename) == 0
|
393
|
-
@@pstore.transaction do |ps|
|
394
|
-
ps[:all_tags] = all_tags = determine_tags('list')
|
395
|
-
ps[:writable_tags] = determine_tags('listw')
|
396
|
-
map = {}
|
397
|
-
all_tags.each { |k| map[unify(k)] = k }
|
398
|
-
ps[:all_tags_map] = map
|
399
|
-
end
|
400
|
-
end
|
401
|
-
end
|
402
|
-
|
403
|
-
def self.determine_tags arg
|
404
|
-
output = `#{@@cmd} -#{arg}`
|
405
|
-
lines = output.split(/\n/) #Fixed by kro44 - add parentheses
|
406
|
-
tags = Set.new
|
407
|
-
lines.each do |line|
|
408
|
-
next unless line =~ /^\s/
|
409
|
-
tags |= line.chomp.split
|
410
|
-
end
|
411
|
-
tags
|
412
|
-
end
|
413
|
-
|
414
|
-
|
415
|
-
# Hash with indifferent access:
|
416
|
-
# DateTimeOriginal == datetimeoriginal == date_time_original
|
417
|
-
class TagHash < Hash # :nodoc:
|
418
|
-
def[] k
|
419
|
-
super(unify(k))
|
420
|
-
end
|
421
|
-
def []= k, v
|
422
|
-
super(unify(k), v)
|
423
|
-
end
|
424
|
-
def delete k
|
425
|
-
super(unify(k))
|
426
|
-
end
|
427
|
-
|
428
|
-
def unify tag
|
429
|
-
MiniExiftool.unify tag
|
430
|
-
end
|
431
|
-
end
|
432
|
-
|
433
|
-
end
|
434
|
-
|
435
|
-
# Add to_a to Numerical if it's not yet defined
|
436
|
-
unless Numeric.instance_methods.include? 'to_a'
|
437
|
-
class Numeric
|
438
|
-
def to_a
|
439
|
-
[self]
|
440
|
-
end
|
441
|
-
end
|
442
|
-
end
|
443
|
-
|
444
|
-
# Test if we can run the Exiftool command
|
445
|
-
MiniExiftool.exiftool_version
|