apetag 1.1.3 → 1.1.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/apetag.rb +50 -31
- data/test/test_apetag.rb +28 -0
- metadata +4 -4
data/apetag.rb
CHANGED
@@ -11,10 +11,8 @@
|
|
11
11
|
# used on any file type and is not limited to storing just audio file metadata).
|
12
12
|
#
|
13
13
|
# The module is in written in pure Ruby, so it should be useable on all
|
14
|
-
# platforms that Ruby supports. It is developed and tested on OpenBSD
|
15
|
-
#
|
16
|
-
# on 1.8.4+. Modifying the code to work with previous version shouldn't be
|
17
|
-
# difficult, though there aren't any plans to do so.
|
14
|
+
# platforms that Ruby supports. It is developed and tested on OpenBSD
|
15
|
+
# with ruby 1.8 and ruby 1.9.
|
18
16
|
#
|
19
17
|
# General Use:
|
20
18
|
#
|
@@ -44,26 +42,6 @@
|
|
44
42
|
# from the latest release.
|
45
43
|
#
|
46
44
|
# (1) http://wiki.hydrogenaudio.org/index.php?title=APEv2_specification
|
47
|
-
#
|
48
|
-
# Copyright (c) 2007 Jeremy Evans
|
49
|
-
#
|
50
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
51
|
-
# of this software and associated documentation files (the "Software"), to deal
|
52
|
-
# in the Software without restriction, including without limitation the rights
|
53
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
54
|
-
# copies of the Software, and to permit persons to whom the Software is
|
55
|
-
# furnished to do so, subject to the following conditions:
|
56
|
-
#
|
57
|
-
# The above copyright notice and this permission notice shall be included in
|
58
|
-
# all copies or substantial portions of the Software.
|
59
|
-
#
|
60
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
61
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
62
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
63
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
64
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
65
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
66
|
-
# SOFTWARE.
|
67
45
|
|
68
46
|
require 'cicphash'
|
69
47
|
|
@@ -106,7 +84,7 @@ class ApeItem < Array
|
|
106
84
|
raise ApeTagError, "Missing key-value separator at offset #{offset}" unless key_end
|
107
85
|
raise ApeTagError, "Invalid item length at offset #{offset}" if (next_item_start=length + key_end + 1) > data.length
|
108
86
|
begin
|
109
|
-
item = ApeItem.
|
87
|
+
item = ApeItem.new_from_parse(data[offset...key_end], data[(key_end+1)...next_item_start].split("\0"))
|
110
88
|
rescue ArgumentError =>e
|
111
89
|
raise ApeTagError, "ArgumentError: #{e.message}"
|
112
90
|
end
|
@@ -135,16 +113,17 @@ class ApeItem < Array
|
|
135
113
|
# Set key if valid, otherwise raise ApeTagError.
|
136
114
|
def key=(key)
|
137
115
|
raise ApeTagError, "Invalid APE key" unless valid_key?(key)
|
138
|
-
@key = key
|
116
|
+
@key = encoded_key(key)
|
139
117
|
end
|
140
|
-
|
118
|
+
|
141
119
|
# The on disk representation of the entire ApeItem.
|
142
120
|
# Raise ApeTagError if ApeItem is invalid.
|
143
121
|
def raw
|
144
122
|
raise ApeTagError, "Invalid key, value, APE type, or Read-Only Flag" unless valid?
|
145
123
|
flags = ITEM_TYPES.index(ape_type) * 2 + (read_only ? 1 : 0)
|
146
|
-
|
147
|
-
|
124
|
+
k = RUBY_VERSION >= '1.9' ? key.dup.force_encoding('BINARY') : key
|
125
|
+
sv = RUBY_VERSION >= '1.9' ? string_value.dup.force_encoding('BINARY') : string_value
|
126
|
+
"#{[sv.length, flags].pack('VN')}#{k}\0#{sv}"
|
148
127
|
end
|
149
128
|
|
150
129
|
# Set read only flag if valid, otherwise raise ApeTagError.
|
@@ -170,7 +149,9 @@ class ApeItem < Array
|
|
170
149
|
|
171
150
|
# Check if the given key is a valid APE key (string, 2 <= length <= 255, not containing invalid characters or keys).
|
172
151
|
def valid_key?(key)
|
173
|
-
key.is_a?(String)
|
152
|
+
return false unless key.is_a?(String)
|
153
|
+
return false unless key = encoded_key(key)
|
154
|
+
key.length >= 2 && key.length <= 255 && (key !~ BAD_KEY_RE rescue false)
|
174
155
|
end
|
175
156
|
|
176
157
|
# Check if the given read only flag is valid (boolean).
|
@@ -181,6 +162,13 @@ class ApeItem < Array
|
|
181
162
|
# Check if the string value is valid UTF-8.
|
182
163
|
def valid_value?
|
183
164
|
begin
|
165
|
+
if RUBY_VERSION >= '1.9'
|
166
|
+
begin
|
167
|
+
map!{|v| v.to_s.encode('UTF-8')}
|
168
|
+
rescue EncodingError
|
169
|
+
return false
|
170
|
+
end
|
171
|
+
end
|
184
172
|
string_value.unpack('U*') if ape_type == 'utf8' || ape_type == 'external'
|
185
173
|
rescue ArgumentError
|
186
174
|
false
|
@@ -188,6 +176,37 @@ class ApeItem < Array
|
|
188
176
|
true
|
189
177
|
end
|
190
178
|
end
|
179
|
+
|
180
|
+
if RUBY_VERSION >= '1.9.0'
|
181
|
+
def self.new_from_parse(key, value)
|
182
|
+
new(key.force_encoding('US-ASCII'), value.map{|v| v.to_s.force_encoding('UTF-8')})
|
183
|
+
end
|
184
|
+
|
185
|
+
def encoded_key(key)
|
186
|
+
begin
|
187
|
+
key.encode('US-ASCII')
|
188
|
+
rescue EncodingError
|
189
|
+
return false
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def normalize_encodings
|
194
|
+
map!{|v| v.to_s.encode('UTF-8')}
|
195
|
+
self
|
196
|
+
end
|
197
|
+
else
|
198
|
+
def self.new_from_parse(key, value)
|
199
|
+
new(key, value)
|
200
|
+
end
|
201
|
+
|
202
|
+
def encoded_key(key)
|
203
|
+
key
|
204
|
+
end
|
205
|
+
|
206
|
+
def normalize_encodings
|
207
|
+
self
|
208
|
+
end
|
209
|
+
end
|
191
210
|
end
|
192
211
|
|
193
212
|
# Contains all of the ApeItems found in the filename/file given.
|
@@ -421,7 +440,7 @@ class ApeTag
|
|
421
440
|
def normalize_fields
|
422
441
|
new_fields = CICPHash.new
|
423
442
|
fields.each do |key, value|
|
424
|
-
new_fields[key] = ApeItem.create(key, value)
|
443
|
+
new_fields[key] = ApeItem.create(key, value).normalize_encodings
|
425
444
|
end
|
426
445
|
@fields = new_fields
|
427
446
|
end
|
data/test/test_apetag.rb
CHANGED
@@ -445,4 +445,32 @@ class ApeTagTest < Test::Unit::TestCase
|
|
445
445
|
assert_equal 0, get_size(filename)
|
446
446
|
File.delete(filename)
|
447
447
|
end
|
448
|
+
|
449
|
+
if RUBY_VERSION > '1.9.0'
|
450
|
+
def test_apeitem_encoding
|
451
|
+
ApeTag.new(StringIO.new(EXAMPLE_APE_TAG)).fields.each do |k, vs|
|
452
|
+
assert_equal 'US-ASCII', k.encoding.name
|
453
|
+
assert_equal 'US-ASCII', vs.key.encoding.name
|
454
|
+
vs.each{|v| assert_equal 'UTF-8', v.encoding.name}
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
458
|
+
def test_item_and_key_encoding
|
459
|
+
filename = 'test.apetag'
|
460
|
+
File.new(filename,'wb').close
|
461
|
+
utf8_key = File.read('test/utf-8.key', :mode=>'rb:UTF-8')
|
462
|
+
utf8_values = File.read('test/utf-8.values', :mode=>'rb:UTF-8')
|
463
|
+
utf16_key = File.read('test/utf-16be.key', :mode=>'rb:UTF-16BE')
|
464
|
+
utf16_values = File.read('test/utf-16be.values', :mode=>'rb:UTF-16BE')
|
465
|
+
latin1_values = File.read('test/latin1.values', :mode=>'rb:ISO-8859-1')
|
466
|
+
ApeTag.new(filename).update do |f|
|
467
|
+
f[utf16_key] = utf16_values.split('\n'.force_encoding('UTF-16BE'))
|
468
|
+
f['foo'] = latin1_values.split('\n'.force_encoding('ISO-8859-1'))
|
469
|
+
end
|
470
|
+
f = ApeTag.new(filename).fields
|
471
|
+
assert_equal utf8_values.split('\n'.force_encoding('UTF-8')), f[utf8_key]
|
472
|
+
assert_equal utf8_values.split('\n'.force_encoding('UTF-8')), f['foo']
|
473
|
+
File.delete(filename)
|
474
|
+
end
|
475
|
+
end
|
448
476
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: apetag
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 1.1.
|
9
|
+
- 4
|
10
|
+
version: 1.1.4
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jeremy Evans
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-01-
|
18
|
+
date: 2011-01-21 00:00:00 -08:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|