1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * https://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.commons.compress.archivers.zip;
20
21 import java.util.Arrays;
22
23 /**
24 * Wrapper for extra field data that doesn't conform to the recommended format of header-tag + size + data.
25 *
26 * <p>
27 * The header-id is artificial (and not listed as a known ID in <a href="https://www.pkware.com/documents/casestudies/APPNOTE.TXT">APPNOTE.TXT</a>). Since it
28 * isn't used anywhere except to satisfy the ZipExtraField contract it shouldn't matter anyway.
29 * </p>
30 *
31 * @since 1.1
32 * @NotThreadSafe
33 */
34 public final class UnparseableExtraFieldData implements ZipExtraField {
35 private static final ZipShort HEADER_ID = new ZipShort(0xACC1);
36
37 private byte[] localFileData;
38 private byte[] centralDirectoryData;
39
40 /**
41 * The actual data to put into central directory.
42 *
43 * @return The CentralDirectoryData value
44 */
45 @Override
46 public byte[] getCentralDirectoryData() {
47 return centralDirectoryData == null ? getLocalFileDataData() : ZipUtil.copy(centralDirectoryData);
48 }
49
50 /**
51 * Length of the complete extra field in the central directory.
52 *
53 * @return The CentralDirectoryLength value
54 */
55 @Override
56 public ZipShort getCentralDirectoryLength() {
57 return centralDirectoryData == null ? getLocalFileDataLength() : new ZipShort(centralDirectoryData.length);
58 }
59
60 /**
61 * The Header-ID.
62 *
63 * @return a completely arbitrary value that should be ignored.
64 */
65 @Override
66 public ZipShort getHeaderId() {
67 return HEADER_ID;
68 }
69
70 /**
71 * The actual data to put into local file data.
72 *
73 * @return The LocalFileDataData value
74 */
75 @Override
76 public byte[] getLocalFileDataData() {
77 return ZipUtil.copy(localFileData);
78 }
79
80 /**
81 * Length of the complete extra field in the local file data.
82 *
83 * @return The LocalFileDataLength value
84 */
85 @Override
86 public ZipShort getLocalFileDataLength() {
87 return ZipShort.lengthOf(localFileData);
88 }
89
90 /**
91 * Populate data from this array as if it was in central directory data.
92 *
93 * @param buffer the buffer to read data from
94 * @param offset offset into buffer to read data
95 * @param length the length of data
96 */
97 @Override
98 public void parseFromCentralDirectoryData(final byte[] buffer, final int offset, final int length) {
99 centralDirectoryData = Arrays.copyOfRange(buffer, offset, offset + length);
100 if (localFileData == null) {
101 parseFromLocalFileData(buffer, offset, length);
102 }
103 }
104
105 /**
106 * Populate data from this array as if it was in local file data.
107 *
108 * @param buffer the buffer to read data from
109 * @param offset offset into buffer to read data
110 * @param length the length of data
111 */
112 @Override
113 public void parseFromLocalFileData(final byte[] buffer, final int offset, final int length) {
114 localFileData = Arrays.copyOfRange(buffer, offset, offset + length);
115 }
116
117 }