• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
18 package org.apache.commons.compress.archivers.zip;
19 
20 /**
21  * Parser/encoder for the "general purpose bit" field in ZIP's local
22  * file and central directory headers.
23  *
24  * @since 1.1
25  * @NotThreadSafe
26  */
27 public final class GeneralPurposeBit implements Cloneable {
28 
29     /**
30      * Indicates that the file is encrypted.
31      */
32     private static final int ENCRYPTION_FLAG = 1 << 0;
33 
34     /**
35      * Indicates the size of the sliding dictionary used by the compression method 6 (imploding).
36      * <ul>
37      *   <li>0: 4096 bytes</li>
38      *   <li>1: 8192 bytes</li>
39      * </ul>
40      */
41     private static final int SLIDING_DICTIONARY_SIZE_FLAG = 1 << 1;
42 
43     /**
44      * Indicates the number of Shannon-Fano trees used by the compression method 6 (imploding).
45      * <ul>
46      *   <li>0: 2 trees (lengths, distances)</li>
47      *   <li>1: 3 trees (literals, lengths, distances)</li>
48      * </ul>
49      */
50     private static final int NUMBER_OF_SHANNON_FANO_TREES_FLAG = 1 << 2;
51 
52     /**
53      * Indicates that a data descriptor stored after the file contents
54      * will hold CRC and size information.
55      */
56     private static final int DATA_DESCRIPTOR_FLAG = 1 << 3;
57 
58     /**
59      * Indicates strong encryption.
60      */
61     private static final int STRONG_ENCRYPTION_FLAG = 1 << 6;
62 
63     /**
64      * Indicates that filenames are written in UTF-8.
65      *
66      * <p>The only reason this is public is that {@link
67      * ZipArchiveOutputStream#EFS_FLAG} was public in Apache Commons
68      * Compress 1.0 and we needed a substitute for it.</p>
69      */
70     public static final int UFT8_NAMES_FLAG = 1 << 11;
71 
72     private boolean languageEncodingFlag = false;
73     private boolean dataDescriptorFlag = false;
74     private boolean encryptionFlag = false;
75     private boolean strongEncryptionFlag = false;
76     private int slidingDictionarySize;
77     private int numberOfShannonFanoTrees;
78 
GeneralPurposeBit()79     public GeneralPurposeBit() {
80     }
81 
82     /**
83      * whether the current entry uses UTF8 for file name and comment.
84      * @return whether the current entry uses UTF8 for file name and comment.
85      */
usesUTF8ForNames()86     public boolean usesUTF8ForNames() {
87         return languageEncodingFlag;
88     }
89 
90     /**
91      * whether the current entry will use UTF8 for file name and comment.
92      * @param b whether the current entry will use UTF8 for file name and comment.
93      */
useUTF8ForNames(final boolean b)94     public void useUTF8ForNames(final boolean b) {
95         languageEncodingFlag = b;
96     }
97 
98     /**
99      * whether the current entry uses the data descriptor to store CRC
100      * and size information.
101      * @return whether the current entry uses the data descriptor to store CRC
102      * and size information
103      */
usesDataDescriptor()104     public boolean usesDataDescriptor() {
105         return dataDescriptorFlag;
106     }
107 
108     /**
109      * whether the current entry will use the data descriptor to store
110      * CRC and size information.
111      * @param b whether the current entry will use the data descriptor to store
112      * CRC and size information
113      */
useDataDescriptor(final boolean b)114     public void useDataDescriptor(final boolean b) {
115         dataDescriptorFlag = b;
116     }
117 
118     /**
119      * whether the current entry is encrypted.
120      * @return whether the current entry is encrypted
121      */
usesEncryption()122     public boolean usesEncryption() {
123         return encryptionFlag;
124     }
125 
126     /**
127      * whether the current entry will be encrypted.
128      * @param b whether the current entry will be encrypted
129      */
useEncryption(final boolean b)130     public void useEncryption(final boolean b) {
131         encryptionFlag = b;
132     }
133 
134     /**
135      * whether the current entry is encrypted using strong encryption.
136      * @return whether the current entry is encrypted using strong encryption
137      */
usesStrongEncryption()138     public boolean usesStrongEncryption() {
139         return encryptionFlag && strongEncryptionFlag;
140     }
141 
142     /**
143      * whether the current entry will be encrypted  using strong encryption.
144      * @param b whether the current entry will be encrypted  using strong encryption
145      */
useStrongEncryption(final boolean b)146     public void useStrongEncryption(final boolean b) {
147         strongEncryptionFlag = b;
148         if (b) {
149             useEncryption(true);
150         }
151     }
152 
153     /**
154      * Returns the sliding dictionary size used by the compression method 6 (imploding).
155      */
getSlidingDictionarySize()156     int getSlidingDictionarySize() {
157         return slidingDictionarySize;
158     }
159 
160     /**
161      * Returns the number of trees used by the compression method 6 (imploding).
162      */
getNumberOfShannonFanoTrees()163     int getNumberOfShannonFanoTrees() {
164         return numberOfShannonFanoTrees;
165     }
166 
167     /**
168      * Encodes the set bits in a form suitable for ZIP archives.
169      * @return the encoded general purpose bits
170      */
encode()171     public byte[] encode() {
172         final byte[] result = new byte[2];
173         encode(result, 0);
174         return result;
175     }
176 
177 
178     /**
179      * Encodes the set bits in a form suitable for ZIP archives.
180      *
181      * @param buf the output buffer
182      * @param  offset
183      *         The offset within the output buffer of the first byte to be written.
184      *         must be non-negative and no larger than <tt>buf.length-2</tt>
185      */
encode(final byte[] buf, final int offset)186     public void encode(final byte[] buf, final int offset) {
187                 ZipShort.putShort((dataDescriptorFlag ? DATA_DESCRIPTOR_FLAG : 0)
188                         |
189                         (languageEncodingFlag ? UFT8_NAMES_FLAG : 0)
190                         |
191                         (encryptionFlag ? ENCRYPTION_FLAG : 0)
192                         |
193                         (strongEncryptionFlag ? STRONG_ENCRYPTION_FLAG : 0)
194                         , buf, offset);
195     }
196 
197     /**
198      * Parses the supported flags from the given archive data.
199      *
200      * @param data local file header or a central directory entry.
201      * @param offset offset at which the general purpose bit starts
202      * @return parsed flags
203      */
parse(final byte[] data, final int offset)204     public static GeneralPurposeBit parse(final byte[] data, final int offset) {
205         final int generalPurposeFlag = ZipShort.getValue(data, offset);
206         final GeneralPurposeBit b = new GeneralPurposeBit();
207         b.useDataDescriptor((generalPurposeFlag & DATA_DESCRIPTOR_FLAG) != 0);
208         b.useUTF8ForNames((generalPurposeFlag & UFT8_NAMES_FLAG) != 0);
209         b.useStrongEncryption((generalPurposeFlag & STRONG_ENCRYPTION_FLAG) != 0);
210         b.useEncryption((generalPurposeFlag & ENCRYPTION_FLAG) != 0);
211         b.slidingDictionarySize = (generalPurposeFlag & SLIDING_DICTIONARY_SIZE_FLAG) != 0 ? 8192 : 4096;
212         b.numberOfShannonFanoTrees = (generalPurposeFlag & NUMBER_OF_SHANNON_FANO_TREES_FLAG) != 0 ? 3 : 2;
213         return b;
214     }
215 
216     @Override
hashCode()217     public int hashCode() {
218         return 3 * (7 * (13 * (17 * (encryptionFlag ? 1 : 0)
219                                + (strongEncryptionFlag ? 1 : 0))
220                          + (languageEncodingFlag ? 1 : 0))
221                     + (dataDescriptorFlag ? 1 : 0));
222     }
223 
224     @Override
equals(final Object o)225     public boolean equals(final Object o) {
226         if (!(o instanceof GeneralPurposeBit)) {
227             return false;
228         }
229         final GeneralPurposeBit g = (GeneralPurposeBit) o;
230         return g.encryptionFlag == encryptionFlag
231             && g.strongEncryptionFlag == strongEncryptionFlag
232             && g.languageEncodingFlag == languageEncodingFlag
233             && g.dataDescriptorFlag == dataDescriptorFlag;
234     }
235 
236     @Override
clone()237     public Object clone() {
238         try {
239             return super.clone();
240         } catch (final CloneNotSupportedException ex) {
241             // impossible
242             throw new RuntimeException("GeneralPurposeBit is not Cloneable?", ex); //NOSONAR
243         }
244     }
245 }
246