apetag 1.1.2 → 1.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/apetag.rb +13 -5
  2. data/test/test_apetag.rb +47 -40
  3. metadata +69 -40
data/apetag.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # encoding: ascii
2
3
  # This library implements a APEv2 reader/writer.
3
4
  # If called from the command line, it prints out the contents of the APEv2 tag
4
5
  # for the given filename arguments.
@@ -35,9 +36,12 @@
35
36
  # If you find any bugs, would like additional documentation, or want to submit a
36
37
  # patch, please use Rubyforge (http://rubyforge.org/projects/apetag/).
37
38
  #
38
- # The most current source code can be accessed via anonymous SVN at
39
- # svn://code.jeremyevans.net/ruby-apetag/. Note that the library isn't modified
40
- # on a regular basis, so it is unlikely to be different from the latest release.
39
+ # The RDoc for the project is available at http://apetag.rubyforge.org.
40
+ #
41
+ # The most current source code can be accessed via github
42
+ # (http://github.com/jeremyevans/ape_tag_libs). Note that the
43
+ # library isn't modified on a regular basis, so it is unlikely to be different
44
+ # from the latest release.
41
45
  #
42
46
  # (1) http://wiki.hydrogenaudio.org/index.php?title=APEv2_specification
43
47
  #
@@ -101,7 +105,11 @@ class ApeItem < Array
101
105
  key_end = data.index("\0", offset += 8)
102
106
  raise ApeTagError, "Missing key-value separator at offset #{offset}" unless key_end
103
107
  raise ApeTagError, "Invalid item length at offset #{offset}" if (next_item_start=length + key_end + 1) > data.length
104
- item = ApeItem.new(data[offset...key_end], data[(key_end+1)...next_item_start].split("\0"))
108
+ begin
109
+ item = ApeItem.new(data[offset...key_end], data[(key_end+1)...next_item_start].split("\0"))
110
+ rescue ArgumentError =>e
111
+ raise ApeTagError, "ArgumentError: #{e.message}"
112
+ end
105
113
  item.read_only = flags & 1 > 0
106
114
  item.ape_type = ITEM_TYPES[flags/2]
107
115
  return [item, next_item_start]
@@ -162,7 +170,7 @@ class ApeItem < Array
162
170
 
163
171
  # Check if the given key is a valid APE key (string, 2 <= length <= 255, not containing invalid characters or keys).
164
172
  def valid_key?(key)
165
- key.is_a?(String) && key.length >= 2 && key.length <= 255 && key !~ BAD_KEY_RE
173
+ key.is_a?(String) && key.length >= 2 && key.length <= 255 && (key !~ BAD_KEY_RE rescue false)
166
174
  end
167
175
 
168
176
  # Check if the given read only flag is valid (boolean).
@@ -7,11 +7,24 @@ require 'test/unit'
7
7
  EMPTY_APE_TAG = "APETAGEX\320\a\0\0 \0\0\0\0\0\0\0\0\0\0\240\0\0\0\0\0\0\0\0APETAGEX\320\a\0\0 \0\0\0\0\0\0\0\0\0\0\200\0\0\0\0\0\0\0\0TAG\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
8
8
  EXAMPLE_APE_TAG = "APETAGEX\xd0\x07\x00\x00\xb0\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00Track\x001\x04\x00\x00\x00\x00\x00\x00\x00Date\x002007\t\x00\x00\x00\x00\x00\x00\x00Comment\x00XXXX-0000\x0b\x00\x00\x00\x00\x00\x00\x00Title\x00Love Cheese\x0b\x00\x00\x00\x00\x00\x00\x00Artist\x00Test Artist\x16\x00\x00\x00\x00\x00\x00\x00Album\x00Test Album\x00Other AlbumAPETAGEX\xd0\x07\x00\x00\xb0\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00TAGLove Cheese\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Test Artist\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Test Album, Other Album\x00\x00\x00\x00\x00\x00\x002007XXXX-0000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xff"
9
9
  EXAMPLE_APE_TAG2 = "APETAGEX\xd0\x07\x00\x00\x99\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00Blah\x00Blah\x04\x00\x00\x00\x00\x00\x00\x00Date\x002007\t\x00\x00\x00\x00\x00\x00\x00Comment\x00XXXX-0000\x0b\x00\x00\x00\x00\x00\x00\x00Artist\x00Test Artist\x16\x00\x00\x00\x00\x00\x00\x00Album\x00Test Album\x00Other AlbumAPETAGEX\xd0\x07\x00\x00\x99\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00TAG\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Test Artist\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Test Album, Other Album\x00\x00\x00\x00\x00\x00\x002007XXXX-0000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff"
10
+ [EMPTY_APE_TAG, EXAMPLE_APE_TAG, EXAMPLE_APE_TAG2].each{|x| x.force_encoding('binary')} if RUBY_VERSION >= '1.9.0'
10
11
  EMPTY_APE_ONLY_TAG, EXAMPLE_APE_ONLY_TAG, EXAMPLE_APE_ONLY_TAG2 = [EMPTY_APE_TAG, EXAMPLE_APE_TAG, EXAMPLE_APE_TAG2].collect{|x|x[0...-128]}
11
12
  EXAMPLE_APE_FIELDS = {"Track"=>["1"], "Comment"=>["XXXX-0000"], "Album"=>["Test Album", "Other Album"], "Title"=>["Love Cheese"], "Artist"=>["Test Artist"], "Date"=>["2007"]}
12
13
  EXAMPLE_APE_FIELDS2 = {"Blah"=>["Blah"], "Comment"=>["XXXX-0000"], "Album"=>["Test Album", "Other Album"], "Artist"=>["Test Artist"], "Date"=>["2007"]}
13
14
  EXAMPLE_APE_TAG_PRETTY_PRINT = "Album: Test Album, Other Album\nArtist: Test Artist\nComment: XXXX-0000\nDate: 2007\nTitle: Love Cheese\nTrack: 1"
14
15
 
16
+ class String
17
+ if RUBY_VERSION > '1.9.0'
18
+ def binary
19
+ force_encoding('binary')
20
+ end
21
+ else
22
+ def binary
23
+ self
24
+ end
25
+ end
26
+ end
27
+
15
28
  class ApeTagTest < Test::Unit::TestCase
16
29
  def get_ape_tag(f, check_id3)
17
30
  f.is_a?(ApeTag) ? f : ApeTag.new(f, check_id3)
@@ -169,17 +182,11 @@ class ApeTagTest < Test::Unit::TestCase
169
182
  assert_equal 1, ac.length
170
183
  assert_equal 'Blah', ac.string_value
171
184
 
172
- # Test create works with random object (Hash in this case)
173
- ac = ApeItem.create('Blah', 'xfe'=>132)
174
- assert_equal ApeItem, ac.class
175
- assert_equal 1, ac.length
176
- assert_equal 'xfe132', ac.string_value
177
-
178
185
  # Test create works with array of mixed objects
179
- ac = ApeItem.create('Blah', ['sadf', 'adsfas', 11, {'xfe'=>132}])
186
+ ac = ApeItem.create('Blah', ['sadf', 'adsfas', 11])
180
187
  assert_equal ApeItem, ac.class
181
- assert_equal 4, ac.length
182
- assert_equal "sadf\0adsfas\00011\0xfe132", ac.string_value
188
+ assert_equal 3, ac.length
189
+ assert_equal "sadf\0adsfas\00011", ac.string_value
183
190
  end
184
191
 
185
192
  # Test ApeItem.parse
@@ -204,25 +211,25 @@ class ApeTagTest < Test::Unit::TestCase
204
211
  assert_raises(ApeTagError){ApeItem.parse(data, 1)}
205
212
 
206
213
  # Test parsing with bad/good flags
207
- data[4] = 8
214
+ data[4,1] = 8.chr
208
215
  assert_raises(ApeTagError){ApeItem.parse(data, 0)}
209
- data[4] = 0
216
+ data[4,1] = 0.chr
210
217
  assert_nothing_raised{ApeItem.parse(data, 0)}
211
218
 
212
219
  # Test parsing with length longer than string
213
- data[0] = 9
220
+ data[0,1] = 9.chr
214
221
  assert_raises(ApeTagError){ApeItem.parse(data, 0)}
215
222
 
216
223
  # Test parsing with length shorter than string gives valid ApeItem
217
224
  # Of course, the next item will probably be parsed incorrectly
218
- data[0] = 3
225
+ data[0,1] = 3.chr
219
226
  assert_nothing_raised{ai, offset = ApeItem.parse(data, 0)}
220
227
  assert_equal 16, offset
221
228
  assert_equal "BlaH", ai.key
222
229
  assert_equal "BlA", ai.string_value
223
230
 
224
231
  # Test parsing gets correct key end
225
- data[12] = '3'
232
+ data[12,1] = "3"
226
233
  assert_nothing_raised{ai, offset = ApeItem.parse(data, 0)}
227
234
  assert_equal "BlaH3BlAh", ai.key
228
235
  assert_equal "XYZ", ai.string_value
@@ -239,41 +246,41 @@ class ApeTagTest < Test::Unit::TestCase
239
246
  assert_nothing_raised{ApeTag.new(StringIO.new(data)).raw}
240
247
 
241
248
  # Test read only tags work
242
- data[20] = 1
249
+ data[20,1] = 1.chr
243
250
  assert_nothing_raised{ApeTag.new(StringIO.new(data)).raw}
244
251
 
245
252
  # Test other flags values don't work
246
253
  2.upto(255) do |i|
247
- data[20] = i
254
+ data[20,1] = i.chr
248
255
  assert_raises(ApeTagError){ApeTag.new(StringIO.new(data)).raw}
249
256
  end
250
- data[20] = 1
257
+ data[20,1] = 1.chr
251
258
  2.upto(255) do |i|
252
- data[52] = i
259
+ data[52,1] = i.chr
253
260
  assert_raises(ApeTagError){ApeTag.new(StringIO.new(data)).raw}
254
- data[20] = i
261
+ data[20,1] = i.chr
255
262
  assert_raises(ApeTagError){ApeTag.new(StringIO.new(data)).raw}
256
263
  end
257
264
 
258
265
  # Test footer size less than minimum size (32)
259
- data[44] = 31
266
+ data[44,1] = 31.chr
260
267
  assert_raises(ApeTagError){ApeTag.new(StringIO.new(data)).raw}
261
- data[44] = 0
268
+ data[44,1] = 0.chr
262
269
  assert_raises(ApeTagError){ApeTag.new(StringIO.new(data)).raw}
263
270
 
264
271
  # Test tag size > 8192, when both larger than file and smaller than file
265
- data[44] = 225
266
- data[45] = 31
272
+ data[44,1] = 225.chr
273
+ data[45,1] = 31.chr
267
274
  assert_raises(ApeTagError){ApeTag.new(StringIO.new(data)).raw}
268
275
  assert_raises(ApeTagError){ApeTag.new(StringIO.new(' '*8192+data)).raw}
269
276
 
270
277
  data = EMPTY_APE_TAG.dup
271
278
  # Test unmatching header and footer tag size, with footer size wrong
272
- data[44] = 33
279
+ data[44,1] = 33.chr
273
280
  assert_raises(ApeTagError){ApeTag.new(StringIO.new(data)).raw}
274
281
 
275
282
  # Test matching header and footer but size to large for file
276
- data[12] = 33
283
+ data[12,1] = 33.chr
277
284
  assert_raises(ApeTagError){ApeTag.new(StringIO.new(data)).raw}
278
285
 
279
286
  # Test that header and footer size isn't too large for file, but doesn't
@@ -282,51 +289,51 @@ class ApeTagTest < Test::Unit::TestCase
282
289
  assert_raises(ApeTagError){ApeTag.new(StringIO.new(data)).raw}
283
290
 
284
291
  # Test unmatching header and footer tag size, with header size wrong
285
- data[45] = 32
292
+ data[45,1] = 32.chr
286
293
  assert_raises(ApeTagError){ApeTag.new(StringIO.new(data)).raw}
287
294
 
288
295
  data = EMPTY_APE_TAG.dup
289
296
  # Test item count greater than maximum (64)
290
- data[48] = 65
297
+ data[48,1] = 65.chr
291
298
  assert_raises(ApeTagError){ApeTag.new(StringIO.new(data)).raw}
292
299
 
293
300
  # Test item count greater than possible given tag size
294
- data[48] = 1
301
+ data[48,1] = 1.chr
295
302
  assert_raises(ApeTagError){ApeTag.new(StringIO.new(data)).raw}
296
303
 
297
304
  # Test unmatched header and footer item count, header size wrong
298
- data[48] = 0
299
- data[16] = 1
305
+ data[48,1] = 0.chr
306
+ data[16,1] = 1.chr
300
307
  assert_raises(ApeTagError){ApeTag.new(StringIO.new(data)).raw}
301
308
 
302
309
  # Test unmatched header and footer item count, footer size wrong
303
310
  data = EXAMPLE_APE_TAG.dup
304
- data[208-16] -=1
311
+ data[208-16] = 5.chr
305
312
  assert_raises(ApeTagError){ApeTag.new(StringIO.new(data)).fields}
306
313
 
307
314
  # Test missing/corrupt header
308
315
  data = EMPTY_APE_TAG.dup
309
- data[0] = 0
316
+ data[0,1] = 0.chr
310
317
  assert_raises(ApeTagError){ApeTag.new(StringIO.new(data)).fields}
311
318
 
312
319
  # Test parsing bad first item size
313
320
  data = EXAMPLE_APE_TAG.dup
314
- data[32] +=1
321
+ data[32,1] = 2.chr
315
322
  assert_raises(ApeTagError){ApeTag.new(StringIO.new(data)).fields}
316
323
 
317
324
  # Test parsing bad first item invalid key
318
325
  data = EXAMPLE_APE_TAG.dup
319
- data[40] = 0
326
+ data[40,1] = 0.chr
320
327
  assert_raises(ApeTagError){ApeTag.new(StringIO.new(data)).fields}
321
328
 
322
329
  # Test parsing bad first item key end
323
330
  data = EXAMPLE_APE_TAG.dup
324
- data[45] = 1
331
+ data[45,1] = 1.chr
325
332
  assert_raises(ApeTagError){ApeTag.new(StringIO.new(data)).fields}
326
333
 
327
334
  # Test parsing bad second item length too long
328
335
  data = EXAMPLE_APE_TAG.dup
329
- data[47] = 255
336
+ data[47,1] = 255.chr
330
337
  assert_raises(ApeTagError){ApeTag.new(StringIO.new(data)).fields}
331
338
 
332
339
  # Test parsing case insensitive duplicate keys
@@ -340,11 +347,11 @@ class ApeTagTest < Test::Unit::TestCase
340
347
 
341
348
  # Test parsing incorrect item counts
342
349
  data = EXAMPLE_APE_TAG.dup
343
- data[16] -= 1
344
- data[192] -= 1
350
+ data[16,1] = 5.chr
351
+ data[192,1] = 5.chr
345
352
  assert_raises(ApeTagError){ApeTag.new(StringIO.new(data)).fields}
346
- data[16] += 2
347
- data[192] += 2
353
+ data[16,1] = 7.chr
354
+ data[192,1] = 7.chr
348
355
  assert_raises(ApeTagError){ApeTag.new(StringIO.new(data)).fields}
349
356
 
350
357
  # Test updating works in a case insensitive manner
metadata CHANGED
@@ -1,54 +1,83 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.9.4
3
- specification_version: 1
4
2
  name: apetag
5
3
  version: !ruby/object:Gem::Version
6
- version: 1.1.2
7
- date: 2007-11-07 00:00:00 -08:00
8
- summary: APEv2 Tag Reader/Writer
9
- require_paths:
10
- - .
11
- email: code@jeremyevans.net
12
- homepage:
13
- rubyforge_project: apetag
14
- description:
15
- autorequire: apetag
16
- default_executable:
17
- bindir: bin
18
- has_rdoc: true
19
- required_ruby_version: !ruby/object:Gem::Version::Requirement
20
- requirements:
21
- - - ">"
22
- - !ruby/object:Gem::Version
23
- version: 0.0.0
24
- version:
4
+ hash: 21
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 1
9
+ - 3
10
+ version: 1.1.3
25
11
  platform: ruby
26
- signing_key:
27
- cert_chain:
28
- post_install_message:
29
12
  authors:
30
13
  - Jeremy Evans
31
- files:
32
- - apetag.rb
33
- test_files:
34
- - test/test_apetag.rb
35
- rdoc_options: []
36
-
37
- extra_rdoc_files: []
38
-
39
- executables: []
40
-
41
- extensions: []
42
-
43
- requirements: []
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
44
17
 
18
+ date: 2011-01-16 00:00:00 -08:00
19
+ default_executable:
45
20
  dependencies:
46
21
  - !ruby/object:Gem::Dependency
47
22
  name: cicphash
48
- version_requirement:
49
- version_requirements: !ruby/object:Gem::Version::Requirement
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
50
26
  requirements:
51
27
  - - ">="
52
28
  - !ruby/object:Gem::Version
29
+ hash: 23
30
+ segments:
31
+ - 1
32
+ - 0
33
+ - 0
53
34
  version: 1.0.0
54
- version:
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ description:
38
+ email: code@jeremyevans.net
39
+ executables: []
40
+
41
+ extensions: []
42
+
43
+ extra_rdoc_files: []
44
+
45
+ files:
46
+ - apetag.rb
47
+ - test/test_apetag.rb
48
+ has_rdoc: true
49
+ homepage: http://apetag.rubyforge.org
50
+ licenses: []
51
+
52
+ post_install_message:
53
+ rdoc_options: []
54
+
55
+ require_paths:
56
+ - .
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ hash: 3
63
+ segments:
64
+ - 0
65
+ version: "0"
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ hash: 3
72
+ segments:
73
+ - 0
74
+ version: "0"
75
+ requirements: []
76
+
77
+ rubyforge_project: apetag
78
+ rubygems_version: 1.3.7
79
+ signing_key:
80
+ specification_version: 3
81
+ summary: APEv2 Tag Reader/Writer
82
+ test_files:
83
+ - test/test_apetag.rb