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 f43c608  COMPRESS-479 use strategy pattern to handle unparseable extra 
fields
f43c608 is described below

commit f43c608cf422817a3280cb2a2cbe749ee090d9d3
Author: Stefan Bodewig <bode...@apache.org>
AuthorDate: Fri Aug 16 08:10:12 2019 +0200

    COMPRESS-479 use strategy pattern to handle unparseable extra fields
---
 .../compress/archivers/zip/ExtraFieldUtils.java    | 67 ++++++++++++----------
 .../zip/UnparseableExtraFieldBehavior.java         | 49 ++++++++++++++++
 2 files changed, 86 insertions(+), 30 deletions(-)

diff --git 
a/src/main/java/org/apache/commons/compress/archivers/zip/ExtraFieldUtils.java 
b/src/main/java/org/apache/commons/compress/archivers/zip/ExtraFieldUtils.java
index 24e4893..aa54bac 100644
--- 
a/src/main/java/org/apache/commons/compress/archivers/zip/ExtraFieldUtils.java
+++ 
b/src/main/java/org/apache/commons/compress/archivers/zip/ExtraFieldUtils.java
@@ -134,7 +134,7 @@ public class ExtraFieldUtils {
      * @since 1.1
      */
     public static ZipExtraField[] parse(final byte[] data, final boolean local,
-                                        final UnparseableExtraField 
onUnparseableData)
+                                        final UnparseableExtraFieldBehavior 
onUnparseableData)
         throws ZipException {
         return parse(data, local, onUnparseableData, ParseErrorBehavior.THROW);
     }
@@ -157,7 +157,7 @@ public class ExtraFieldUtils {
      * @since 1.19
      */
     public static ZipExtraField[] parse(final byte[] data, final boolean local,
-                                        final UnparseableExtraField 
onUnparseableData,
+                                        final UnparseableExtraFieldBehavior 
onUnparseableData,
                                         final ParseErrorBehavior onParseError)
         throws ZipException {
         final List<ZipExtraField> v = new ArrayList<>();
@@ -167,35 +167,15 @@ public class ExtraFieldUtils {
             final ZipShort headerId = new ZipShort(data, start);
             final int length = new ZipShort(data, start + 2).getValue();
             if (start + WORD + length > data.length) {
-                switch(onUnparseableData.getKey()) {
-                case UnparseableExtraField.THROW_KEY:
-                    throw new ZipException("Bad extra field starting at "
-                                           + start + ".  Block length of "
-                                           + length + " bytes exceeds 
remaining"
-                                           + " data of "
-                                           + (data.length - start - WORD)
-                                           + " bytes.");
-                case UnparseableExtraField.READ_KEY:
-                    final UnparseableExtraFieldData field =
-                        new UnparseableExtraFieldData();
-                    if (local) {
-                        field.parseFromLocalFileData(data, start,
-                                                     data.length - start);
-                    } else {
-                        field.parseFromCentralDirectoryData(data, start,
-                                                            data.length - 
start);
-                    }
+                ZipExtraField field = 
onUnparseableData.onUnparseableExtraField(data, start, data.length - start,
+                    local, length);
+                if (field != null) {
                     v.add(field);
-                    //$FALL-THROUGH$
-                case UnparseableExtraField.SKIP_KEY:
-                    // since we cannot parse the data we must assume
-                    // the extra field consumes the whole rest of the
-                    // available data
-                    break LOOP;
-                default:
-                    throw new ZipException("Unknown UnparseableExtraField key: 
"
-                                           + onUnparseableData.getKey());
                 }
+                // since we cannot parse the data we must assume
+                // the extra field consumes the whole rest of the
+                // available data
+                break LOOP;
             }
             switch (onParseError) {
             case MAKE_UNRECOGNIZED:
@@ -328,7 +308,7 @@ public class ExtraFieldUtils {
      *
      * @since 1.1
      */
-    public static final class UnparseableExtraField {
+    public static final class UnparseableExtraField implements 
UnparseableExtraFieldBehavior {
         /**
          * Key for "throw an exception" action.
          */
@@ -373,6 +353,33 @@ public class ExtraFieldUtils {
          * @return the key
          */
         public int getKey() { return key; }
+
+        @Override
+        public ZipExtraField onUnparseableExtraField(byte[] data, int off, int 
len, boolean local,
+            int claimedLength) throws ZipException {
+            switch(key) {
+            case THROW_KEY:
+                throw new ZipException("Bad extra field starting at "
+                                       + off + ".  Block length of "
+                                       + claimedLength + " bytes exceeds 
remaining"
+                                       + " data of "
+                                       + (len - WORD)
+                                       + " bytes.");
+            case READ_KEY:
+                final UnparseableExtraFieldData field = new 
UnparseableExtraFieldData();
+                if (local) {
+                    field.parseFromLocalFileData(data, off, len);
+                } else {
+                    field.parseFromCentralDirectoryData(data, off, len);
+                }
+                return field;
+            case SKIP_KEY:
+                return null;
+            default:
+                throw new ZipException("Unknown UnparseableExtraField key: " + 
key);
+            }
+        }
+
     }
 
     /**
diff --git 
a/src/main/java/org/apache/commons/compress/archivers/zip/UnparseableExtraFieldBehavior.java
 
b/src/main/java/org/apache/commons/compress/archivers/zip/UnparseableExtraFieldBehavior.java
new file mode 100644
index 0000000..09d596a
--- /dev/null
+++ 
b/src/main/java/org/apache/commons/compress/archivers/zip/UnparseableExtraFieldBehavior.java
@@ -0,0 +1,49 @@
+/*
+ * 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.zip.ZipException;
+
+/**
+ * Handles extra field data that doesn't follow the recommended
+ * pattern for extra fields with a two-byte key and a two-byte length.
+ *
+ * @since 1.19
+ */
+public interface UnparseableExtraFieldBehavior {
+    /**
+     * Decides what to do with extra field data that doesn't follow the 
recommended pattern.
+     *
+     * @param data the array of extra field data
+     * @param off offset into data where the unparseable data starts
+     * @param len the length of unparseable data
+     * @param local whether the extra field data stems from the local
+     * file header. If this is false then the data is part if the
+     * central directory header extra data.
+     * @param claimedLength length of the extra field claimed by the
+     * third and forth byte if it did follow the recommended pattern
+     *
+     * @return null if the data should be ignored or an extra field
+     * implementation that represents the data
+     * @throws ZipException if an error occurs or unparseable extra
+     * fields must not be accepted
+     */
+    ZipExtraField onUnparseableExtraField(byte[] data, int off, int len, 
boolean local,
+        int claimedLength) throws ZipException;
+}

Reply via email to