1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.compress.archivers.zip;
18
19 import static org.apache.commons.compress.archivers.zip.ZipConstants.WORD;
20
21 import java.io.Serializable;
22
23 import org.apache.commons.compress.utils.ByteUtils;
24
25 /**
26 * Utility class that represents a four byte integer with conversion rules for the little-endian byte order of ZIP files.
27 *
28 * @Immutable
29 */
30 public final class ZipLong implements Cloneable, Serializable {
31
32 private static final long serialVersionUID = 1L;
33
34 /** Central File Header Signature */
35 public static final ZipLong CFH_SIG = new ZipLong(0X02014B50L);
36
37 /** Local File Header Signature */
38 public static final ZipLong LFH_SIG = new ZipLong(0X04034B50L);
39
40 /**
41 * Data Descriptor signature.
42 *
43 * <p>
44 * Actually, PKWARE uses this as marker for split/spanned archives and other archivers have started to use it as Data Descriptor signature (as well).
45 * </p>
46 *
47 * @since 1.1
48 */
49 public static final ZipLong DD_SIG = new ZipLong(0X08074B50L);
50
51 /**
52 * Value stored in size and similar fields if ZIP64 extensions are used.
53 *
54 * @since 1.3
55 */
56 static final ZipLong ZIP64_MAGIC = new ZipLong(ZipConstants.ZIP64_MAGIC);
57
58 /**
59 * 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).
60 *
61 * <p>
62 * This is the "PK00" prefix found in some archives.
63 * </p>
64 *
65 * @since 1.5
66 */
67 public static final ZipLong SINGLE_SEGMENT_SPLIT_MARKER = new ZipLong(0X30304B50L);
68
69 /**
70 * Archive extra data record signature.
71 *
72 * @since 1.5
73 */
74 public static final ZipLong AED_SIG = new ZipLong(0X08064B50L);
75
76 /**
77 * Gets value as four bytes in big-endian byte order.
78 *
79 * @param value the value to convert
80 * @return value as four bytes in big-endian byte order
81 */
82 public static byte[] getBytes(final long value) {
83 final byte[] result = new byte[WORD];
84 putLong(value, result, 0);
85 return result;
86 }
87
88 /**
89 * Helper method to get the value as a Java long from a four-byte array
90 *
91 * @param bytes the array of bytes
92 * @return the corresponding Java long value
93 */
94 public static long getValue(final byte[] bytes) {
95 return getValue(bytes, 0);
96 }
97
98 /**
99 * Helper method to get the value as a Java long from four bytes starting at given array offset
100 *
101 * @param bytes the array of bytes
102 * @param offset the offset to start
103 * @return the corresponding Java long value
104 */
105 public static long getValue(final byte[] bytes, final int offset) {
106 return ByteUtils.fromLittleEndian(bytes, offset, 4);
107 }
108
109 /**
110 * put the value as four bytes in big-endian byte order.
111 *
112 * @param value the Java long to convert to bytes
113 * @param buf the output buffer
114 * @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}
115 */
116
117 public static void putLong(final long value, final byte[] buf, final int offset) {
118 ByteUtils.toLittleEndian(buf, value, offset, 4);
119 }
120
121 private final long value;
122
123 /**
124 * Constructs a new instance from bytes.
125 *
126 * @param bytes the bytes to store as a ZipLong
127 */
128 public ZipLong(final byte[] bytes) {
129 this(bytes, 0);
130 }
131
132 /**
133 * Creates instance from the four bytes starting at offset.
134 *
135 * @param bytes the bytes to store as a ZipLong
136 * @param offset the offset to start
137 */
138 public ZipLong(final byte[] bytes, final int offset) {
139 value = getValue(bytes, offset);
140 }
141
142 /**
143 * create instance from a Java int.
144 *
145 * @param value the int to store as a ZipLong
146 * @since 1.15
147 */
148 public ZipLong(final int value) {
149 this.value = value;
150 }
151
152 /**
153 * Creates instance from a number.
154 *
155 * @param value the long to store as a ZipLong
156 */
157 public ZipLong(final long value) {
158 this.value = value;
159 }
160
161 @Override
162 public Object clone() {
163 try {
164 return super.clone();
165 } catch (final CloneNotSupportedException cnfe) {
166 // impossible
167 throw new UnsupportedOperationException(cnfe); // NOSONAR
168 }
169 }
170
171 /**
172 * Override to make two instances with same value equal.
173 *
174 * @param o an object to compare
175 * @return true if the objects are equal
176 */
177 @Override
178 public boolean equals(final Object o) {
179 if (!(o instanceof ZipLong)) {
180 return false;
181 }
182 return value == ((ZipLong) o).getValue();
183 }
184
185 /**
186 * Gets value as four bytes in big-endian byte order.
187 *
188 * @return value as four bytes in big-endian order
189 */
190 public byte[] getBytes() {
191 return getBytes(value);
192 }
193
194 /**
195 * Gets value as a (signed) Java int
196 *
197 * @return value as int
198 * @since 1.15
199 */
200 public int getIntValue() {
201 return (int) value;
202 }
203
204 /**
205 * Gets value as Java long.
206 *
207 * @return value as a long
208 */
209 public long getValue() {
210 return value;
211 }
212
213 /**
214 * Override to make two instances with same value equal.
215 *
216 * @return the value stored in the ZipLong
217 */
218 @Override
219 public int hashCode() {
220 return (int) value;
221 }
222
223 public void putLong(final byte[] buf, final int offset) {
224 putLong(value, buf, offset);
225 }
226
227 @Override
228 public String toString() {
229 return "ZipLong value: " + value;
230 }
231 }