1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package entagged.audioformats.ape.util;
20
21 import java.io.IOException;
22 import java.io.RandomAccessFile;
23 import entagged.audioformats.Tag;
24 import entagged.audioformats.ape.ApeTag;
25 import entagged.audioformats.exceptions.CannotReadException;
26 import entagged.audioformats.generic.Utils;
27
28 public class ApeTagReader {
29
30 public Tag read(RandomAccessFile raf) throws CannotReadException, IOException {
31 ApeTag tag = new ApeTag();
32
33
34 raf.seek( raf.length() - 32 );
35
36 byte[] b = new byte[8];
37 raf.read(b);
38
39 String tagS = new String( b );
40 if(!tagS.equals( "APETAGEX" )){
41 throw new CannotReadException("There is no APE Tag in this file");
42 }
43
44
45 b = new byte[4];
46 raf.read( b );
47 int version = Utils.getNumber(b, 0,3);
48 if(version != 2000) {
49 throw new CannotReadException("APE Tag other than version 2.0 are not supported");
50 }
51
52
53 b = new byte[4];
54 raf.read( b );
55 long tagSize = Utils.getLongNumber(b, 0,3);
56
57
58 b = new byte[4];
59 raf.read( b );
60 int itemNumber = Utils.getNumber(b, 0,3);
61
62
63 b = new byte[4];
64 raf.read( b );
65
66
67 raf.seek(raf.length() - tagSize);
68
69 for(int i = 0; i<itemNumber; i++) {
70
71 b = new byte[4];
72 raf.read( b );
73 int contentLength = Utils.getNumber(b, 0,3);
74 if(contentLength > 500000)
75 throw new CannotReadException("Item size is much too large: "+contentLength+" bytes");
76
77
78 b = new byte[4];
79 raf.read( b );
80
81 boolean binary = ((b[0]&0x06) >> 1) == 1;
82
83 int j = 0;
84 while(raf.readByte() != 0)
85 j++;
86 raf.seek(raf.getFilePointer() - j -1);
87 int fieldSize = j;
88
89
90 b = new byte[fieldSize];
91 raf.read( b );
92 raf.skipBytes(1);
93 String field = new String(b);
94
95
96 b = new byte[contentLength];
97 raf.read( b );
98 if(!binary)
99 tag.add(new ApeTagTextField(field, new String(b, "UTF-8")));
100 else
101 tag.add(new ApeTagBinaryField(field, b));
102 }
103
104 return tag;
105 }
106 }