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; +}