View Javadoc
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.compressors.gzip;
20  
21  import java.nio.charset.Charset;
22  import java.nio.charset.StandardCharsets;
23  import java.util.LinkedHashMap;
24  import java.util.Map;
25  
26  import org.apache.commons.compress.compressors.FileNameUtil;
27  
28  /**
29   * Utility code for the GZIP compression format.
30   *
31   * @see <a href="https://datatracker.ietf.org/doc/html/rfc1952">RFC 1952 GZIP File Format Specification</a>
32   * @ThreadSafe
33   */
34  public class GzipUtils {
35  
36      /** Header flag indicating a comment follows the header. */
37      static final int FCOMMENT = 0x10;
38  
39      /** Header flag indicating an EXTRA subfields collection follows the header. */
40      static final int FEXTRA = 0x04;
41  
42      /** Header flag indicating a header CRC follows the header. */
43      static final int FHCRC = 0x02;
44  
45      private static final FileNameUtil fileNameUtil;
46  
47      /** Header flag indicating a file name follows the header. */
48      static final int FNAME = 0x08;
49  
50      static final int FRESERVED = 0xE0;
51  
52      /**
53       * Charset for file name and comments per the <a href="https://tools.ietf.org/html/rfc1952">GZIP File Format Specification</a>.
54       */
55      static final Charset GZIP_ENCODING = StandardCharsets.ISO_8859_1;
56  
57      /**
58       * Member header ID1 (IDentification 1).
59       *
60       * See <a href="https://datatracker.ietf.org/doc/html/rfc1952#page-5">RFC1952</a> 2.3.1. Member header and trailer.
61       */
62      static final int ID1 = 31;
63  
64      /**
65       * Member header ID2 (IDentification 2).
66       *
67       * See <a href="https://datatracker.ietf.org/doc/html/rfc1952#page-5">RFC1952</a> 2.3.1. Member header and trailer.
68       */
69      static final int ID2 = 139;
70  
71      /**
72       * Member header XFL (eXtra FLags) when the "deflate" method (CM = 8) is set, then XFL = 2 means the compressor used maximum compression (slowest
73       * algorithm).
74       *
75       * See <a href="https://datatracker.ietf.org/doc/html/rfc1952#page-5">RFC1952</a> 2.3.1. Member header and trailer.
76       */
77      static final byte XFL_MAX_COMPRESSION = 2;
78  
79      /**
80       * Member header XFL (eXtra FLags) when the "deflate" method (CM = 8) is set, then XFL = 4 means the compressor used the fastest algorithm.
81       *
82       * See <a href="https://datatracker.ietf.org/doc/html/rfc1952#page-5">RFC1952</a> 2.3.1. Member header and trailer.
83       */
84      static final byte XFL_MAX_SPEED = 4;
85  
86      static final byte XFL_UNKNOWN = 0;
87  
88      /**
89       * Using {@link LinkedHashMap} so {@code .tgz} is preferred over {@code .taz} as compressed extension of {@code .tar} as FileNameUtil will use the first one
90       * found.
91       */
92      static {
93          final Map<String, String> uncompressSuffix = new LinkedHashMap<>();
94          uncompressSuffix.put(".tgz", ".tar");
95          uncompressSuffix.put(".taz", ".tar");
96          uncompressSuffix.put(".svgz", ".svg");
97          uncompressSuffix.put(".cpgz", ".cpio");
98          uncompressSuffix.put(".wmz", ".wmf");
99          uncompressSuffix.put(".emz", ".emf");
100         uncompressSuffix.put(".gz", "");
101         uncompressSuffix.put(".z", "");
102         uncompressSuffix.put("-gz", "");
103         uncompressSuffix.put("-z", "");
104         uncompressSuffix.put("_z", "");
105         fileNameUtil = new FileNameUtil(uncompressSuffix, ".gz");
106     }
107     /**
108      * Maps the given file name to the name that the file should have after compression with gzip. Common file types with custom suffixes for compressed
109      * versions are automatically detected and correctly mapped. For example the name "package.tar" is mapped to "package.tgz". If no custom mapping is
110      * applicable, then the default ".gz" suffix is appended to the file name.
111      *
112      * @param fileName name of a file
113      * @return name of the corresponding compressed file
114      * @deprecated Use {@link #getCompressedFileName(String)}.
115      */
116     @Deprecated
117     public static String getCompressedFilename(final String fileName) {
118         return fileNameUtil.getCompressedFileName(fileName);
119     }
120 
121     /**
122      * Maps the given file name to the name that the file should have after compression with gzip. Common file types with custom suffixes for compressed
123      * versions are automatically detected and correctly mapped. For example the name "package.tar" is mapped to "package.tgz". If no custom mapping is
124      * applicable, then the default ".gz" suffix is appended to the file name.
125      *
126      * @param fileName name of a file
127      * @return name of the corresponding compressed file
128      * @since 1.25.0
129      */
130     public static String getCompressedFileName(final String fileName) {
131         return fileNameUtil.getCompressedFileName(fileName);
132     }
133 
134     /**
135      * Maps the given name of a gzip-compressed file to the name that the file should have after uncompression. Commonly used file type specific suffixes like
136      * ".tgz" or ".svgz" are automatically detected and correctly mapped. For example the name "package.tgz" is mapped to "package.tar". And any file names with
137      * the generic ".gz" suffix (or any other generic gzip suffix) is mapped to a name without that suffix. If no gzip suffix is detected, then the file name is
138      * returned unmapped.
139      *
140      * @param fileName name of a file
141      * @return name of the corresponding uncompressed file
142      * @deprecated Use {@link #getUncompressedFileName(String)}.
143      */
144     @Deprecated
145     public static String getUncompressedFilename(final String fileName) {
146         return fileNameUtil.getUncompressedFileName(fileName);
147     }
148 
149     /**
150      * Maps the given name of a gzip-compressed file to the name that the file should have after uncompression. Commonly used file type specific suffixes like
151      * ".tgz" or ".svgz" are automatically detected and correctly mapped. For example the name "package.tgz" is mapped to "package.tar". And any file names with
152      * the generic ".gz" suffix (or any other generic gzip suffix) is mapped to a name without that suffix. If no gzip suffix is detected, then the file name is
153      * returned unmapped.
154      *
155      * @param fileName name of a file
156      * @return name of the corresponding uncompressed file
157      * @since 1.25.0
158      */
159     public static String getUncompressedFileName(final String fileName) {
160         return fileNameUtil.getUncompressedFileName(fileName);
161     }
162 
163     /**
164      * Detects common gzip suffixes in the given file name.
165      *
166      * @param fileName name of a file
167      * @return {@code true} if the file name has a common gzip suffix, {@code false} otherwise
168      * @deprecated Use {@link #isCompressedFileName(String)}.
169      */
170     @Deprecated
171     public static boolean isCompressedFilename(final String fileName) {
172         return fileNameUtil.isCompressedFileName(fileName);
173     }
174 
175     /**
176      * Detects common gzip suffixes in the given file name.
177      *
178      * @param fileName name of a file
179      * @return {@code true} if the file name has a common gzip suffix, {@code false} otherwise
180      * @since 1.25.0
181      */
182     public static boolean isCompressedFileName(final String fileName) {
183         return fileNameUtil.isCompressedFileName(fileName);
184     }
185 
186     /** Private constructor to prevent instantiation of this utility class. */
187     private GzipUtils() {
188     }
189 
190 }