1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.compress.archivers.zip;
19
20 import static java.nio.charset.StandardCharsets.UTF_8;
21
22 import java.util.Arrays;
23 import java.util.zip.CRC32;
24 import java.util.zip.ZipException;
25
26
27
28
29
30
31 public abstract class AbstractUnicodeExtraField implements ZipExtraField {
32 private long nameCRC32;
33 private byte[] unicodeName;
34 private byte[] data;
35
36
37
38
39 protected AbstractUnicodeExtraField() {
40 }
41
42
43
44
45
46
47
48 protected AbstractUnicodeExtraField(final String text, final byte[] bytes) {
49 this(text, bytes, 0, bytes.length);
50 }
51
52
53
54
55
56
57
58
59
60 protected AbstractUnicodeExtraField(final String text, final byte[] bytes, final int off, final int len) {
61 final CRC32 crc32 = new CRC32();
62 crc32.update(bytes, off, len);
63 nameCRC32 = crc32.getValue();
64
65 unicodeName = text.getBytes(UTF_8);
66 }
67
68 private void assembleData() {
69 if (unicodeName == null) {
70 return;
71 }
72
73 data = new byte[5 + unicodeName.length];
74
75 data[0] = 0x01;
76 System.arraycopy(ZipLong.getBytes(nameCRC32), 0, data, 1, 4);
77 System.arraycopy(unicodeName, 0, data, 5, unicodeName.length);
78 }
79
80 @Override
81 public byte[] getCentralDirectoryData() {
82 if (data == null) {
83 assembleData();
84 }
85 byte[] b = null;
86 if (data != null) {
87 b = Arrays.copyOf(data, data.length);
88 }
89 return b;
90 }
91
92 @Override
93 public ZipShort getCentralDirectoryLength() {
94 if (data == null) {
95 assembleData();
96 }
97 return new ZipShort(data != null ? data.length : 0);
98 }
99
100 @Override
101 public byte[] getLocalFileDataData() {
102 return getCentralDirectoryData();
103 }
104
105 @Override
106 public ZipShort getLocalFileDataLength() {
107 return getCentralDirectoryLength();
108 }
109
110
111
112
113
114
115 public long getNameCRC32() {
116 return nameCRC32;
117 }
118
119
120
121
122
123
124 public byte[] getUnicodeName() {
125 return unicodeName != null ? Arrays.copyOf(unicodeName, unicodeName.length) : null;
126 }
127
128
129
130
131 @Override
132 public void parseFromCentralDirectoryData(final byte[] buffer, final int offset, final int length) throws ZipException {
133 parseFromLocalFileData(buffer, offset, length);
134 }
135
136 @Override
137 public void parseFromLocalFileData(final byte[] buffer, final int offset, final int length) throws ZipException {
138
139 if (length < 5) {
140 throw new ZipException("UniCode path extra data must have at least 5 bytes.");
141 }
142
143 final int version = buffer[offset];
144
145 if (version != 0x01) {
146 throw new ZipException("Unsupported version [" + version + "] for UniCode path extra data.");
147 }
148
149 nameCRC32 = ZipLong.getValue(buffer, offset + 1);
150 unicodeName = new byte[length - 5];
151 System.arraycopy(buffer, offset + 5, unicodeName, 0, length - 5);
152 data = null;
153 }
154
155
156
157
158
159
160 public void setNameCRC32(final long nameCRC32) {
161 this.nameCRC32 = nameCRC32;
162 data = null;
163 }
164
165
166
167
168
169
170 public void setUnicodeName(final byte[] unicodeName) {
171 if (unicodeName != null) {
172 this.unicodeName = Arrays.copyOf(unicodeName, unicodeName.length);
173 } else {
174 this.unicodeName = null;
175 }
176 data = null;
177 }
178 }