You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by bo...@apache.org on 2019/08/12 20:16:17 UTC

[commons-compress] branch master updated: COMPRESS-479 introduce a parameter class for zip readers

This is an automated email from the ASF dual-hosted git repository.

bodewig pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-compress.git


The following commit(s) were added to refs/heads/master by this push:
     new 0c4f64c  COMPRESS-479 introduce a parameter class for zip readers
0c4f64c is described below

commit 0c4f64c2bebd85a96be8a07b1ad700c7688cbe02
Author: Stefan Bodewig <bo...@apache.org>
AuthorDate: Mon Aug 12 22:15:44 2019 +0200

    COMPRESS-479 introduce a parameter class for zip readers
---
 .../archivers/zip/ZipArchiveInputStream.java       |  56 ++++++--
 .../compress/archivers/zip/ZipEncodingHelper.java  |   2 +-
 .../commons/compress/archivers/zip/ZipFile.java    | 122 ++++++++++-------
 .../compress/archivers/zip/ZipReadingOptions.java  | 146 +++++++++++++++++++++
 .../archivers/ArchiveStreamFactoryTest.java        |  32 ++---
 .../archivers/zip/Maven221MultiVolumeTest.java     |   2 +-
 .../compress/archivers/zip/UTF8ZipFilesTest.java   |   4 +-
 .../zip/ZipFileIgnoringLocalFileHeaderTest.java    |   2 +-
 8 files changed, 282 insertions(+), 84 deletions(-)

diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java b/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java
index 3d33fa4..58b006e 100644
--- a/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java
+++ b/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java
@@ -27,6 +27,7 @@ import java.io.PushbackInputStream;
 import java.math.BigInteger;
 import java.nio.ByteBuffer;
 import java.util.Arrays;
+import java.util.Objects;
 import java.util.zip.CRC32;
 import java.util.zip.DataFormatException;
 import java.util.zip.Inflater;
@@ -80,15 +81,11 @@ import static org.apache.commons.compress.archivers.zip.ZipConstants.ZIP64_MAGIC
  */
 public class ZipArchiveInputStream extends ArchiveInputStream implements InputStreamStatistics {
 
-    /** The zip encoding to use for file names and the file comment. */
-    private final ZipEncoding zipEncoding;
+    private final ZipReadingOptions options;
 
     // the provided encoding (for unit tests)
     final String encoding;
 
-    /** Whether to look for and use Unicode extra fields. */
-    private final boolean useUnicodeExtraFields;
-
     /** Wrapped stream, will always be a PushbackInputStream. */
     private final InputStream in;
 
@@ -168,11 +165,11 @@ public class ZipArchiveInputStream extends ArchiveInputStream implements InputSt
     private int entriesRead = 0;
 
     /**
-     * Create an instance using UTF-8 encoding
+     * Create an instance using the {@link ZipReadingOptions#DEFAULT default reading options}.
      * @param inputStream the stream to wrap
      */
     public ZipArchiveInputStream(final InputStream inputStream) {
-        this(inputStream, ZipEncodingHelper.UTF8);
+        this(inputStream, ZipReadingOptions.DEFAULT);
     }
 
     /**
@@ -183,7 +180,7 @@ public class ZipArchiveInputStream extends ArchiveInputStream implements InputSt
      * @since 1.5
      */
     public ZipArchiveInputStream(final InputStream inputStream, final String encoding) {
-        this(inputStream, encoding, true);
+        this(inputStream, ZipReadingOptions.builder().withEncoding(encoding).build());
     }
 
     /**
@@ -195,7 +192,9 @@ public class ZipArchiveInputStream extends ArchiveInputStream implements InputSt
      * Extra Fields (if present) to set the file names.
      */
     public ZipArchiveInputStream(final InputStream inputStream, final String encoding, final boolean useUnicodeExtraFields) {
-        this(inputStream, encoding, useUnicodeExtraFields, false);
+        this(inputStream, ZipReadingOptions.builder()
+             .withEncoding(encoding).withUseUnicodeExtraFields(useUnicodeExtraFields)
+             .build(), false);
     }
 
     /**
@@ -213,9 +212,37 @@ public class ZipArchiveInputStream extends ArchiveInputStream implements InputSt
                                  final String encoding,
                                  final boolean useUnicodeExtraFields,
                                  final boolean allowStoredEntriesWithDataDescriptor) {
-        this.encoding = encoding;
-        zipEncoding = ZipEncodingHelper.getZipEncoding(encoding);
-        this.useUnicodeExtraFields = useUnicodeExtraFields;
+        this(inputStream, ZipReadingOptions.builder()
+             .withEncoding(encoding).withUseUnicodeExtraFields(useUnicodeExtraFields)
+             .build(), allowStoredEntriesWithDataDescriptor);
+    }
+
+    /**
+     * Create an instance using the specified reading options.
+     * @param inputStream the stream to wrap
+     * @param options the reading options
+     * @throws NullPointerException if {@code options} is null
+     * @since 1.19
+     */
+    public ZipArchiveInputStream(final InputStream inputStream, final ZipReadingOptions options) {
+        this(inputStream, options, false);
+    }
+
+    /**
+     * Create an instance using the specified reading options.
+     * @param inputStream the stream to wrap
+     * @param options the reading options
+     * @param allowStoredEntriesWithDataDescriptor whether the stream
+     * will try to read STORED entries that use a data descriptor
+     * @throws NullPointerException if {@code options} is null
+     * @since 1.19
+     */
+    public ZipArchiveInputStream(final InputStream inputStream, final ZipReadingOptions options,
+                                 final boolean allowStoredEntriesWithDataDescriptor) {
+        this.options = Objects.requireNonNull(options, "options must not be null");
+        this.encoding = options.getZipEncoding() instanceof NioZipEncoding
+            ? ((NioZipEncoding) options.getZipEncoding()).getCharset().name()
+            : null;
         in = new PushbackInputStream(inputStream, buf.capacity());
         this.allowStoredEntriesWithDataDescriptor =
             allowStoredEntriesWithDataDescriptor;
@@ -269,7 +296,8 @@ public class ZipArchiveInputStream extends ArchiveInputStream implements InputSt
 
         final GeneralPurposeBit gpFlag = GeneralPurposeBit.parse(lfhBuf, off);
         final boolean hasUTF8Flag = gpFlag.usesUTF8ForNames();
-        final ZipEncoding entryEncoding = hasUTF8Flag ? ZipEncodingHelper.UTF8_ZIP_ENCODING : zipEncoding;
+        final ZipEncoding entryEncoding = hasUTF8Flag ? ZipEncodingHelper.UTF8_ZIP_ENCODING
+            : options.getZipEncoding();
         current.hasDataDescriptor = gpFlag.usesDataDescriptor();
         current.entry.setGeneralPurposeBit(gpFlag);
 
@@ -314,7 +342,7 @@ public class ZipArchiveInputStream extends ArchiveInputStream implements InputSt
         readFully(extraData);
         current.entry.setExtra(extraData);
 
-        if (!hasUTF8Flag && useUnicodeExtraFields) {
+        if (!hasUTF8Flag && options.getUseUnicodeExtraFields()) {
             ZipUtil.setNameAndCommentFromExtraFields(current.entry, fileName, null);
         }
 
diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/ZipEncodingHelper.java b/src/main/java/org/apache/commons/compress/archivers/zip/ZipEncodingHelper.java
index 0dd605e..d47d31b 100644
--- a/src/main/java/org/apache/commons/compress/archivers/zip/ZipEncodingHelper.java
+++ b/src/main/java/org/apache/commons/compress/archivers/zip/ZipEncodingHelper.java
@@ -32,7 +32,7 @@ public abstract class ZipEncodingHelper {
     /**
      * name of the encoding UTF-8
      */
-    static final String UTF8 = "UTF8";
+    static final String UTF8 = "UTF-8";
 
     /**
      * the encoding UTF-8
diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java b/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java
index 152272b..5f5662d 100644
--- a/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java
+++ b/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java
@@ -39,6 +39,7 @@ import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.zip.Inflater;
 import java.util.zip.ZipException;
 
@@ -109,19 +110,7 @@ public class ZipFile implements Closeable {
     private final Map<String, LinkedList<ZipArchiveEntry>> nameMap =
         new HashMap<>(HASH_SIZE);
 
-    /**
-     * The encoding to use for file names and the file comment.
-     *
-     * <p>For a list of possible values see <a
-     * href="http://java.sun.com/j2se/1.5.0/docs/guide/intl/encoding.doc.html">http://java.sun.com/j2se/1.5.0/docs/guide/intl/encoding.doc.html</a>.
-     * Defaults to UTF-8.</p>
-     */
-    private final String encoding;
-
-    /**
-     * The zip encoding to use for file names and the file comment.
-     */
-    private final ZipEncoding zipEncoding;
+    private final ZipReadingOptions options;
 
     /**
      * File name of actual source.
@@ -134,11 +123,6 @@ public class ZipFile implements Closeable {
     private final SeekableByteChannel archive;
 
     /**
-     * Whether to look for and use Unicode extra fields.
-     */
-    private final boolean useUnicodeExtraFields;
-
-    /**
      * Whether the file is closed.
      */
     private volatile boolean closed = true;
@@ -153,25 +137,27 @@ public class ZipFile implements Closeable {
     private final ByteBuffer cfhBbuf = ByteBuffer.wrap(cfhBuf);
 
     /**
-     * Opens the given file for reading, assuming "UTF8" for file names.
+     * Opens the given file for reading using {@link
+     * ZipReadingOptions#DEFAULT default reading options}.
      *
      * @param f the archive.
      *
      * @throws IOException if an error occurs while reading the file.
      */
     public ZipFile(final File f) throws IOException {
-        this(f, ZipEncodingHelper.UTF8);
+        this(f, ZipReadingOptions.DEFAULT);
     }
 
     /**
-     * Opens the given file for reading, assuming "UTF8".
+     * Opens the given file for reading using {@link
+     * ZipReadingOptions#DEFAULT default reading options}.
      *
      * @param name name of the archive.
      *
      * @throws IOException if an error occurs while reading the file.
      */
     public ZipFile(final String name) throws IOException {
-        this(new File(name), ZipEncodingHelper.UTF8);
+        this(new File(name));
     }
 
     /**
@@ -185,7 +171,7 @@ public class ZipFile implements Closeable {
      * @throws IOException if an error occurs while reading the file.
      */
     public ZipFile(final String name, final String encoding) throws IOException {
-        this(new File(name), encoding, true);
+        this(new File(name), ZipReadingOptions.builder().withEncoding(encoding).build());
     }
 
     /**
@@ -199,7 +185,7 @@ public class ZipFile implements Closeable {
      * @throws IOException if an error occurs while reading the file.
      */
     public ZipFile(final File f, final String encoding) throws IOException {
-        this(f, encoding, true);
+        this(f, ZipReadingOptions.builder().withEncoding(encoding).build());
     }
 
     /**
@@ -216,7 +202,25 @@ public class ZipFile implements Closeable {
      */
     public ZipFile(final File f, final String encoding, final boolean useUnicodeExtraFields)
         throws IOException {
-        this(f, encoding, useUnicodeExtraFields, false);
+        this(f, ZipReadingOptions.builder()
+             .withEncoding(encoding).withUseUnicodeExtraFields(useUnicodeExtraFields)
+             .build());
+    }
+
+    /**
+     * Opens the given file for reading, assuming the specified
+     * options.
+     *
+     * @param f the archive.
+     * @param options the reading options
+     *
+     * @throws IOException if an error occurs while reading the file.
+     * @throws NullPointerException if {@code options} is null
+     * @since 1.19
+     */
+    public ZipFile(final File f, final ZipReadingOptions options)
+        throws IOException {
+        this(f, options, false);
     }
 
     /**
@@ -234,25 +238,24 @@ public class ZipFile implements Closeable {
      * true}.</p>
      *
      * @param f the archive.
-     * @param encoding the encoding to use for file names, use null
-     * for the platform's default encoding
-     * @param useUnicodeExtraFields whether to use InfoZIP Unicode
-     * Extra Fields (if present) to set the file names.
+     * @param options the reading options
      * @param ignoreLocalFileHeader whether to ignore information
      * stored inside the local file header (see the notes in this method's javadoc)
      *
      * @throws IOException if an error occurs while reading the file.
+     * @throws NullPointerException if {@code options} is null
      * @since 1.19
      */
-    public ZipFile(final File f, final String encoding, final boolean useUnicodeExtraFields,
+    public ZipFile(final File f, final ZipReadingOptions options,
                    final boolean ignoreLocalFileHeader)
         throws IOException {
         this(Files.newByteChannel(f.toPath(), EnumSet.of(StandardOpenOption.READ)),
-             f.getAbsolutePath(), encoding, useUnicodeExtraFields, true, ignoreLocalFileHeader);
+             f.getAbsolutePath(), options, true, ignoreLocalFileHeader);
     }
 
     /**
-     * Opens the given channel for reading, assuming "UTF8" for file names.
+     * Opens the given channel for reading using {@link
+     * ZipReadingOptions#DEFAULT default reading options}.
      *
      * <p>{@link
      * org.apache.commons.compress.utils.SeekableInMemoryByteChannel}
@@ -265,7 +268,7 @@ public class ZipFile implements Closeable {
      */
     public ZipFile(final SeekableByteChannel channel)
             throws IOException {
-        this(channel, "unknown archive", ZipEncodingHelper.UTF8, true);
+        this(channel, "unknown archive", ZipReadingOptions.DEFAULT);
     }
 
     /**
@@ -285,7 +288,7 @@ public class ZipFile implements Closeable {
      */
     public ZipFile(final SeekableByteChannel channel, final String encoding)
         throws IOException {
-        this(channel, "unknown archive", encoding, true);
+        this(channel, "unknown archive", ZipReadingOptions.builder().withEncoding(encoding).build());
     }
 
     /**
@@ -309,7 +312,30 @@ public class ZipFile implements Closeable {
     public ZipFile(final SeekableByteChannel channel, final String archiveName,
                    final String encoding, final boolean useUnicodeExtraFields)
         throws IOException {
-        this(channel, archiveName, encoding, useUnicodeExtraFields, false, false);
+        this(channel, archiveName, ZipReadingOptions.builder()
+             .withEncoding(encoding).withUseUnicodeExtraFields(useUnicodeExtraFields)
+             .build());
+    }
+
+    /**
+     * Opens the given channel for reading, assuming the specified
+     * reading options.
+     *
+     * <p>{@link
+     * org.apache.commons.compress.utils.SeekableInMemoryByteChannel}
+     * allows you to read from an in-memory archive.</p>
+     *
+     * @param channel the archive.
+     * @param archiveName name of the archive, used for error messages only.
+     * @param options the reading options
+     *
+     * @throws IOException if an error occurs while reading the file.
+     * @throws NullPointerException if {@code options} is null
+     * @since 1.19
+     */
+    public ZipFile(final SeekableByteChannel channel, final String archiveName,
+                   final ZipReadingOptions options) throws IOException {
+        this(channel, archiveName, options, false);
     }
 
     /**
@@ -331,31 +357,27 @@ public class ZipFile implements Closeable {
      *
      * @param channel the archive.
      * @param archiveName name of the archive, used for error messages only.
-     * @param encoding the encoding to use for file names, use null
-     * for the platform's default encoding
-     * @param useUnicodeExtraFields whether to use InfoZIP Unicode
-     * Extra Fields (if present) to set the file names.
+     * @param options the reading options
      * @param ignoreLocalFileHeader whether to ignore information
      * stored inside the local file header (see the notes in this method's javadoc)
      *
      * @throws IOException if an error occurs while reading the file.
+     * @throws NullPointerException if {@code options} is null
      * @since 1.19
      */
     public ZipFile(final SeekableByteChannel channel, final String archiveName,
-                   final String encoding, final boolean useUnicodeExtraFields,
+                   final ZipReadingOptions options,
                    final boolean ignoreLocalFileHeader)
         throws IOException {
-        this(channel, archiveName, encoding, useUnicodeExtraFields, false, ignoreLocalFileHeader);
+        this(channel, archiveName, options, false, ignoreLocalFileHeader);
     }
 
     private ZipFile(final SeekableByteChannel channel, final String archiveName,
-                    final String encoding, final boolean useUnicodeExtraFields,
+                    final ZipReadingOptions options,
                     final boolean closeOnError, final boolean ignoreLocalFileHeader)
         throws IOException {
         this.archiveName = archiveName;
-        this.encoding = encoding;
-        this.zipEncoding = ZipEncodingHelper.getZipEncoding(encoding);
-        this.useUnicodeExtraFields = useUnicodeExtraFields;
+        this.options = Objects.requireNonNull(options, "options must not be null");
         archive = channel;
         boolean success = false;
         try {
@@ -380,7 +402,9 @@ public class ZipFile implements Closeable {
      * @return null if using the platform's default character encoding.
      */
     public String getEncoding() {
-        return encoding;
+        return options.getZipEncoding() instanceof NioZipEncoding
+            ? ((NioZipEncoding) options.getZipEncoding()).getCharset().name()
+            : null;
     }
 
     /**
@@ -626,7 +650,7 @@ public class ZipFile implements Closeable {
     public String getUnixSymlink(final ZipArchiveEntry entry) throws IOException {
         if (entry != null && entry.isUnixSymlink()) {
             try (InputStream in = getInputStream(entry)) {
-                return zipEncoding.decode(IOUtils.toByteArray(in));
+                return options.getZipEncoding().decode(IOUtils.toByteArray(in));
             }
         }
         return null;
@@ -739,7 +763,7 @@ public class ZipFile implements Closeable {
         final GeneralPurposeBit gpFlag = GeneralPurposeBit.parse(cfhBuf, off);
         final boolean hasUTF8Flag = gpFlag.usesUTF8ForNames();
         final ZipEncoding entryEncoding =
-            hasUTF8Flag ? ZipEncodingHelper.UTF8_ZIP_ENCODING : zipEncoding;
+            hasUTF8Flag ? ZipEncodingHelper.UTF8_ZIP_ENCODING : options.getZipEncoding();
         if (hasUTF8Flag) {
             ze.setNameSource(ZipArchiveEntry.NameSource.NAME_WITH_EFS_FLAG);
         }
@@ -802,7 +826,7 @@ public class ZipFile implements Closeable {
         IOUtils.readFully(archive, ByteBuffer.wrap(comment));
         ze.setComment(entryEncoding.decode(comment));
 
-        if (!hasUTF8Flag && useUnicodeExtraFields) {
+        if (!hasUTF8Flag && options.getUseUnicodeExtraFields()) {
             noUTF8Flag.put(ze, new NameAndComment(fileName, comment));
         }
 
diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/ZipReadingOptions.java b/src/main/java/org/apache/commons/compress/archivers/zip/ZipReadingOptions.java
new file mode 100644
index 0000000..386490e
--- /dev/null
+++ b/src/main/java/org/apache/commons/compress/archivers/zip/ZipReadingOptions.java
@@ -0,0 +1,146 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+package org.apache.commons.compress.archivers.zip;
+
+import java.util.Objects;
+
+/**
+ * Collects options that control parsing of ZIP archives.
+ *
+ * @since 1.19
+ */
+public final class ZipReadingOptions {
+    private static final ZipEncoding DEFAULT_ZIPENCODING = ZipEncodingHelper.UTF8_ZIP_ENCODING;
+    private static final boolean DEFAULT_USEUNICODEEXTRAFIELDS = true;
+    private static final ExtraFieldUtils.ParseErrorBehavior DEFAULT_EXTRAFIELDPARSEERRORBEHAVIOR =
+        ExtraFieldUtils.ParseErrorBehavior.MAKE_UNRECOGNIZED;
+
+    private final ZipEncoding zipEncoding;
+    private final boolean useUnicodeExtraFields;
+    private final ExtraFieldUtils.ParseErrorBehavior extraFieldParseErrorBehavior;
+
+    /**
+     * The default reading options.
+     *
+     * <ul>
+     * <li>UTF-8 encoding</li>
+     * <li>use unicode extra fields when available</li>
+     * <li>convert invalid extra fields into {@link UnparseableExtraFieldData}</li>
+     * </ul>
+     */
+    public static final ZipReadingOptions DEFAULT = new ZipReadingOptions(DEFAULT_ZIPENCODING,
+        DEFAULT_USEUNICODEEXTRAFIELDS, DEFAULT_EXTRAFIELDPARSEERRORBEHAVIOR);
+
+    private ZipReadingOptions(ZipEncoding zipEncoding, boolean useUnicodeExtraFields,
+        ExtraFieldUtils.ParseErrorBehavior extraFieldParseErrorBehavior) {
+        this.zipEncoding = zipEncoding;
+        this.useUnicodeExtraFields = useUnicodeExtraFields;
+        this.extraFieldParseErrorBehavior = extraFieldParseErrorBehavior;
+    }
+
+    /**
+     * The zip encoding to use for file names and the file comment.
+     */
+    public ZipEncoding getZipEncoding() {
+        return zipEncoding;
+    }
+
+    /**
+     * Whether to look for and use Unicode extra fields.
+     */
+    public boolean getUseUnicodeExtraFields() {
+        return useUnicodeExtraFields;
+    }
+
+    /**
+     * How to handle extra fields that are generally supported by
+     * Commons Compress but cannot be parsed in an archive.
+     *
+     * <p>The archive may contain corrupt extra fields or use a
+     * version not supported by Commons Compress.</p>
+     */
+    public ExtraFieldUtils.ParseErrorBehavior getExtraFieldParseErrorBehavior() {
+        return extraFieldParseErrorBehavior;
+    }
+
+    /**
+     * Obtains a builder for {@link ZipReadingOptions}.
+     */
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    /**
+     * Builder for {@link ZipReadingOptions}.
+     */
+    public static class Builder {
+        private ZipEncoding zipEncoding = DEFAULT_ZIPENCODING;
+        private boolean useUnicodeExtraFields = DEFAULT_USEUNICODEEXTRAFIELDS;
+        private ExtraFieldUtils.ParseErrorBehavior extraFieldParseErrorBehavior =
+            DEFAULT_EXTRAFIELDPARSEERRORBEHAVIOR;
+
+        /**
+         * Configures the ZIP encoding.
+         *
+         * @throws NullPointException if {@code zipEncoding} is null
+         */
+        public Builder withZipEncoding(ZipEncoding zipEncoding) {
+            this.zipEncoding = Objects.requireNonNull(zipEncoding, "zipEncoding must not be null");
+            return this;
+        }
+
+        /**
+         * Configures the encoding.
+         *
+         * @param encoding name of the encoding to use, {@code null}
+         * means to use the platform's default encoding
+         */
+        public Builder withEncoding(String encoding) {
+            return withZipEncoding(ZipEncodingHelper.getZipEncoding(encoding));
+        }
+
+        /**
+         * Configures whether to use unicode extra fields to configure names and comments.
+         */
+        public Builder withUseUnicodeExtraFields(boolean useUnicodeExtraFields) {
+            this.useUnicodeExtraFields = useUnicodeExtraFields;
+            return this;
+        }
+
+        /**
+         * Configures how to handle extra fields that are generally
+         * supported by Commons Compress but cannot be parsed in an
+         * archive.
+         *
+         * @throws NullPointException if {@code extraFieldParseErrorBehavior} is null
+         */
+        public Builder withextraFieldParseErrorBehavior(ExtraFieldUtils.ParseErrorBehavior extraFieldParseErrorBehavior) {
+            this.extraFieldParseErrorBehavior = Objects.requireNonNull(extraFieldParseErrorBehavior,
+                "extraFieldParseErrorBehavior must not be null");
+            return this;
+        }
+
+        /**
+         * Create the configured {@link ZipReadingOptions}.
+         */
+        public ZipReadingOptions build() {
+            return new ZipReadingOptions(zipEncoding, useUnicodeExtraFields, extraFieldParseErrorBehavior);
+        }
+    }
+}
diff --git a/src/test/java/org/apache/commons/compress/archivers/ArchiveStreamFactoryTest.java b/src/test/java/org/apache/commons/compress/archivers/ArchiveStreamFactoryTest.java
index f7113ac..3f3e3f7 100644
--- a/src/test/java/org/apache/commons/compress/archivers/ArchiveStreamFactoryTest.java
+++ b/src/test/java/org/apache/commons/compress/archivers/ArchiveStreamFactoryTest.java
@@ -195,9 +195,9 @@ public class ArchiveStreamFactoryTest {
     // The different factory types
     private static final ArchiveStreamFactory FACTORY = new ArchiveStreamFactory();
     private static final ArchiveStreamFactory FACTORY_UTF8 = new ArchiveStreamFactory("UTF-8");
-    private static final ArchiveStreamFactory FACTORY_ASCII = new ArchiveStreamFactory("ASCII");
+    private static final ArchiveStreamFactory FACTORY_ASCII = new ArchiveStreamFactory("US-ASCII");
     private static final ArchiveStreamFactory FACTORY_SET_UTF8 = getFactory("UTF-8");
-    private static final ArchiveStreamFactory FACTORY_SET_ASCII = getFactory("ASCII");
+    private static final ArchiveStreamFactory FACTORY_SET_ASCII = getFactory("US-ASCII");
 
     // Default encoding if none is provided (not even null)
     // The test currently assumes that the output default is the same as the input default
@@ -275,39 +275,39 @@ public class ArchiveStreamFactoryTest {
     static final TestData[] TESTS = {
         new TestData("bla.arj", ArchiveStreamFactory.ARJ, false, ARJ_DEFAULT, FACTORY, "charsetName"),
         new TestData("bla.arj", ArchiveStreamFactory.ARJ, false, "UTF-8", FACTORY_UTF8, "charsetName"),
-        new TestData("bla.arj", ArchiveStreamFactory.ARJ, false, "ASCII", FACTORY_ASCII, "charsetName"),
+        new TestData("bla.arj", ArchiveStreamFactory.ARJ, false, "US-ASCII", FACTORY_ASCII, "charsetName"),
         new TestData("bla.arj", ArchiveStreamFactory.ARJ, false, "UTF-8", FACTORY_SET_UTF8, "charsetName"),
-        new TestData("bla.arj", ArchiveStreamFactory.ARJ, false, "ASCII", FACTORY_SET_ASCII, "charsetName"),
+        new TestData("bla.arj", ArchiveStreamFactory.ARJ, false, "US-ASCII", FACTORY_SET_ASCII, "charsetName"),
 
         new TestData("bla.cpio", ArchiveStreamFactory.CPIO, true, CPIO_DEFAULT, FACTORY, "encoding"),
         new TestData("bla.cpio", ArchiveStreamFactory.CPIO, true, "UTF-8", FACTORY_UTF8, "encoding"),
-        new TestData("bla.cpio", ArchiveStreamFactory.CPIO, true, "ASCII", FACTORY_ASCII, "encoding"),
+        new TestData("bla.cpio", ArchiveStreamFactory.CPIO, true, "US-ASCII", FACTORY_ASCII, "encoding"),
         new TestData("bla.cpio", ArchiveStreamFactory.CPIO, true, "UTF-8", FACTORY_SET_UTF8, "encoding"),
-        new TestData("bla.cpio", ArchiveStreamFactory.CPIO, true, "ASCII", FACTORY_SET_ASCII, "encoding"),
+        new TestData("bla.cpio", ArchiveStreamFactory.CPIO, true, "US-ASCII", FACTORY_SET_ASCII, "encoding"),
 
         new TestData("bla.dump", ArchiveStreamFactory.DUMP, false, DUMP_DEFAULT, FACTORY, "encoding"),
         new TestData("bla.dump", ArchiveStreamFactory.DUMP, false, "UTF-8", FACTORY_UTF8, "encoding"),
-        new TestData("bla.dump", ArchiveStreamFactory.DUMP, false, "ASCII", FACTORY_ASCII, "encoding"),
+        new TestData("bla.dump", ArchiveStreamFactory.DUMP, false, "US-ASCII", FACTORY_ASCII, "encoding"),
         new TestData("bla.dump", ArchiveStreamFactory.DUMP, false, "UTF-8", FACTORY_SET_UTF8, "encoding"),
-        new TestData("bla.dump", ArchiveStreamFactory.DUMP, false, "ASCII", FACTORY_SET_ASCII, "encoding"),
+        new TestData("bla.dump", ArchiveStreamFactory.DUMP, false, "US-ASCII", FACTORY_SET_ASCII, "encoding"),
 
         new TestData("bla.tar", ArchiveStreamFactory.TAR, true, TAR_DEFAULT, FACTORY, "encoding"),
         new TestData("bla.tar", ArchiveStreamFactory.TAR, true, "UTF-8", FACTORY_UTF8, "encoding"),
-        new TestData("bla.tar", ArchiveStreamFactory.TAR, true, "ASCII", FACTORY_ASCII, "encoding"),
+        new TestData("bla.tar", ArchiveStreamFactory.TAR, true, "US-ASCII", FACTORY_ASCII, "encoding"),
         new TestData("bla.tar", ArchiveStreamFactory.TAR, true, "UTF-8", FACTORY_SET_UTF8, "encoding"),
-        new TestData("bla.tar", ArchiveStreamFactory.TAR, true, "ASCII", FACTORY_SET_ASCII, "encoding"),
+        new TestData("bla.tar", ArchiveStreamFactory.TAR, true, "US-ASCII", FACTORY_SET_ASCII, "encoding"),
 
         new TestData("bla.jar", ArchiveStreamFactory.JAR, true, JAR_DEFAULT, FACTORY, "encoding"),
         new TestData("bla.jar", ArchiveStreamFactory.JAR, true, "UTF-8", FACTORY_UTF8, "encoding"),
-        new TestData("bla.jar", ArchiveStreamFactory.JAR, true, "ASCII", FACTORY_ASCII, "encoding"),
+        new TestData("bla.jar", ArchiveStreamFactory.JAR, true, "US-ASCII", FACTORY_ASCII, "encoding"),
         new TestData("bla.jar", ArchiveStreamFactory.JAR, true, "UTF-8", FACTORY_SET_UTF8, "encoding"),
-        new TestData("bla.jar", ArchiveStreamFactory.JAR, true, "ASCII", FACTORY_SET_ASCII, "encoding"),
+        new TestData("bla.jar", ArchiveStreamFactory.JAR, true, "US-ASCII", FACTORY_SET_ASCII, "encoding"),
 
         new TestData("bla.zip", ArchiveStreamFactory.ZIP, true, ZIP_DEFAULT, FACTORY, "encoding"),
         new TestData("bla.zip", ArchiveStreamFactory.ZIP, true, "UTF-8", FACTORY_UTF8, "encoding"),
-        new TestData("bla.zip", ArchiveStreamFactory.ZIP, true, "ASCII", FACTORY_ASCII, "encoding"),
+        new TestData("bla.zip", ArchiveStreamFactory.ZIP, true, "US-ASCII", FACTORY_ASCII, "encoding"),
         new TestData("bla.zip", ArchiveStreamFactory.ZIP, true, "UTF-8", FACTORY_SET_UTF8, "encoding"),
-        new TestData("bla.zip", ArchiveStreamFactory.ZIP, true, "ASCII", FACTORY_SET_ASCII, "encoding"),
+        new TestData("bla.zip", ArchiveStreamFactory.ZIP, true, "US-ASCII", FACTORY_SET_ASCII, "encoding"),
     };
 
     @Test
@@ -354,8 +354,8 @@ public class ArchiveStreamFactoryTest {
         for(int i = 1; i <= TESTS.length; i++) {
             final TestData test = TESTS[i-1];
             if (test.hasOutputStream) {
-                try (final ArchiveOutputStream ais = getOutputStreamFor(test.type, test.fac)) {
-                    final String field = getField(ais, test.fieldName);
+                try (final ArchiveOutputStream aos = getOutputStreamFor(test.type, test.fac)) {
+                    final String field = getField(aos, test.fieldName);
                     if (!eq(test.expectedEncoding, field)) {
                         System.out.println("Failed test " + i + ". expected: " + test.expectedEncoding + " actual: "
                                 + field + " type: " + test.type);
diff --git a/src/test/java/org/apache/commons/compress/archivers/zip/Maven221MultiVolumeTest.java b/src/test/java/org/apache/commons/compress/archivers/zip/Maven221MultiVolumeTest.java
index 0a905e3..4ce4f56 100644
--- a/src/test/java/org/apache/commons/compress/archivers/zip/Maven221MultiVolumeTest.java
+++ b/src/test/java/org/apache/commons/compress/archivers/zip/Maven221MultiVolumeTest.java
@@ -72,7 +72,7 @@ public class Maven221MultiVolumeTest {
             new FileInputStream(getFile("apache-maven-2.2.1.zip.001"));
         ZipArchiveInputStream zi = null;
         try {
-            zi = new ZipArchiveInputStream(archive,null,false);
+            zi = new ZipArchiveInputStream(archive, (String) null, false);
 
             // these are the entries that are supposed to be processed
             // correctly without any problems
diff --git a/src/test/java/org/apache/commons/compress/archivers/zip/UTF8ZipFilesTest.java b/src/test/java/org/apache/commons/compress/archivers/zip/UTF8ZipFilesTest.java
index 7c745a1..c7ff05b 100644
--- a/src/test/java/org/apache/commons/compress/archivers/zip/UTF8ZipFilesTest.java
+++ b/src/test/java/org/apache/commons/compress/archivers/zip/UTF8ZipFilesTest.java
@@ -134,7 +134,7 @@ public class UTF8ZipFilesTest extends AbstractTestCase {
         final File archive = getFile("utf8-winzip-test.zip");
         ZipFile zf = null;
         try {
-            zf = new ZipFile(archive, null, true);
+            zf = new ZipFile(archive, (String) null, true);
             assertCanRead(zf, ASCII_TXT);
             assertCanRead(zf, EURO_FOR_DOLLAR_TXT);
             assertCanRead(zf, OIL_BARREL_TXT);
@@ -161,7 +161,7 @@ public class UTF8ZipFilesTest extends AbstractTestCase {
             new FileInputStream(getFile("utf8-winzip-test.zip"));
         ZipArchiveInputStream zi = null;
         try {
-            zi = new ZipArchiveInputStream(archive, null, true);
+            zi = new ZipArchiveInputStream(archive, (String) null, true);
             assertEquals(EURO_FOR_DOLLAR_TXT, zi.getNextEntry().getName());
             assertEquals(OIL_BARREL_TXT, zi.getNextEntry().getName());
             assertEquals(ASCII_TXT, zi.getNextEntry().getName());
diff --git a/src/test/java/org/apache/commons/compress/archivers/zip/ZipFileIgnoringLocalFileHeaderTest.java b/src/test/java/org/apache/commons/compress/archivers/zip/ZipFileIgnoringLocalFileHeaderTest.java
index 3d40c03..457192d 100644
--- a/src/test/java/org/apache/commons/compress/archivers/zip/ZipFileIgnoringLocalFileHeaderTest.java
+++ b/src/test/java/org/apache/commons/compress/archivers/zip/ZipFileIgnoringLocalFileHeaderTest.java
@@ -103,6 +103,6 @@ public class ZipFileIgnoringLocalFileHeaderTest {
     }
 
     private static ZipFile openZipWithoutLFH(String fileName) throws IOException {
-        return new ZipFile(AbstractTestCase.getFile(fileName), ZipEncodingHelper.UTF8, true, true);
+        return new ZipFile(AbstractTestCase.getFile(fileName), ZipReadingOptions.DEFAULT, true);
     }
 }