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