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 static org.apache.commons.compress.archivers.zip.ZipConstants.WORD;
22
23 import java.io.Serializable;
24
25 import org.apache.commons.compress.utils.ByteUtils;
26
27 /**
28 * Utility class that represents a four byte integer with conversion rules for the little-endian byte order of ZIP files.
29 *
30 * @Immutable
31 */
32 public final class ZipLong implements Cloneable, Serializable {
33
34 private static final long serialVersionUID = 1L;
35
36 /** Central File Header Signature */
37 public static final ZipLong CFH_SIG = new ZipLong(0X02014B50L);
38
39 /** Local File Header Signature */
40 public static final ZipLong LFH_SIG = new ZipLong(0X04034B50L);
41
42 /**
43 * Data Descriptor signature.
44 *
45 * <p>
46 * Actually, PKWARE uses this as marker for split/spanned archives and other archivers have started to use it as Data Descriptor signature (as well).
47 * </p>
48 *
49 * @since 1.1
50 */
51 public static final ZipLong DD_SIG = new ZipLong(0X08074B50L);
52
53 /**
54 * Value stored in size and similar fields if ZIP64 extensions are used.
55 *
56 * @since 1.3
57 */
58 static final ZipLong ZIP64_MAGIC = new ZipLong(ZipConstants.ZIP64_MAGIC);
59
60 /**
61 * Marks ZIP archives that were supposed to be split or spanned but only needed a single segment in then end (so are actually neither split nor spanned).
62 *
63 * <p>
64 * This is the "PK00" prefix found in some archives.
65 * </p>
66 *
67 * @since 1.5
68 */
69 public static final ZipLong SINGLE_SEGMENT_SPLIT_MARKER = new ZipLong(0X30304B50L);
70
71 /**
72 * Archive extra data record signature.
73 *
74 * @since 1.5
75 */
76 public static final ZipLong AED_SIG = new ZipLong(0X08064B50L);
77
78 /**
79 * Gets value as four bytes in big-endian byte order.
80 *
81 * @param value the value to convert
82 * @return value as four bytes in big-endian byte order
83 */
84 public static byte[] getBytes(final long value) {
85 final byte[] result = new byte[WORD];
86 putLong(value, result, 0);
87 return result;
88 }
89
90 /**
91 * Helper method to get the value as a Java long from a four-byte array
92 *
93 * @param bytes the array of bytes
94 * @return the corresponding Java long value
95 */
96 public static long getValue(final byte[] bytes) {
97 return getValue(bytes, 0);
98 }
99
100 /**
101 * Helper method to get the value as a Java long from four bytes starting at given array offset
102 *
103 * @param bytes the array of bytes
104 * @param offset the offset to start
105 * @return the corresponding Java long value
106 */
107 public static long getValue(final byte[] bytes, final int offset) {
108 return ByteUtils.fromLittleEndian(bytes, offset, 4);
109 }
110
111 /**
112 * Puts a long value in a buffer as four bytes in little-endian byte order.
113 *
114 * @param value the Java long to convert to bytes
115 * @param buf the output buffer
116 * @param offset The offset within the output buffer of the first byte to be written. must be non-negative and no larger than {@code buf.length-4}
117 */
118 public static void putLong(final long value, final byte[] buf, final int offset) {
119 ByteUtils.toLittleEndian(buf, value, offset, 4);
120 }
121
122 private final long value;
123
124 /**
125 * Constructs a new instance from bytes.
126 *
127 * @param bytes the bytes to store as a ZipLong
128 */
129 public ZipLong(final byte[] bytes) {
130 this(bytes, 0);
131 }
132
133 /**
134 * Creates instance from the four bytes starting at offset.
135 *
136 * @param bytes the bytes to store as a ZipLong
137 * @param offset the offset to start
138 */
139 public ZipLong(final byte[] bytes, final int offset) {
140 value = getValue(bytes, offset);
141 }
142
143 /**
144 * create instance from a Java int.
145 *
146 * @param value the int to store as a ZipLong
147 * @since 1.15
148 */
149 public ZipLong(final int value) {
150 this.value = value;
151 }
152
153 /**
154 * Creates instance from a number.
155 *
156 * @param value the long to store as a ZipLong
157 */
158 public ZipLong(final long value) {
159 this.value = value;
160 }
161
162 @Override
163 public Object clone() {
164 try {
165 return super.clone();
166 } catch (final CloneNotSupportedException cnfe) {
167 // impossible
168 throw new UnsupportedOperationException(cnfe); // NOSONAR
169 }
170 }
171
172 /**
173 * Override to make two instances with same value equal.
174 *
175 * @param o an object to compare
176 * @return true if the objects are equal
177 */
178 @Override
179 public boolean equals(final Object o) {
180 if (!(o instanceof ZipLong)) {
181 return false;
182 }
183 return value == ((ZipLong) o).getValue();
184 }
185
186 /**
187 * Gets value as four bytes in big-endian byte order.
188 *
189 * @return value as four bytes in big-endian order
190 */
191 public byte[] getBytes() {
192 return getBytes(value);
193 }
194
195 /**
196 * Gets value as a (signed) Java int
197 *
198 * @return value as int
199 * @since 1.15
200 */
201 public int getIntValue() {
202 return (int) value;
203 }
204
205 /**
206 * Gets value as Java long.
207 *
208 * @return value as a long
209 */
210 public long getValue() {
211 return value;
212 }
213
214 /**
215 * Override to make two instances with same value equal.
216 *
217 * @return the value stored in the ZipLong
218 */
219 @Override
220 public int hashCode() {
221 return (int) value;
222 }
223
224 /**
225 * Puts this long value in a buffer as four bytes in little-endian byte order.
226 *
227 * @param buf the output buffer
228 * @param offset The offset within the output buffer of the first byte to be written. must be non-negative and no larger than {@code buf.length-4}
229 */
230 public void putLong(final byte[] buf, final int offset) {
231 putLong(value, buf, offset);
232 }
233
234 @Override
235 public String toString() {
236 return "ZipLong value: " + value;
237 }
238 }