Return-Path: Delivered-To: apmail-ant-notifications-archive@minotaur.apache.org Received: (qmail 40692 invoked from network); 3 Mar 2009 13:19:08 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 3 Mar 2009 13:19:08 -0000 Received: (qmail 27415 invoked by uid 500); 3 Mar 2009 13:19:08 -0000 Delivered-To: apmail-ant-notifications-archive@ant.apache.org Received: (qmail 27387 invoked by uid 500); 3 Mar 2009 13:19:08 -0000 Mailing-List: contact notifications-help@ant.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@ant.apache.org Delivered-To: mailing list notifications@ant.apache.org Received: (qmail 27378 invoked by uid 99); 3 Mar 2009 13:19:08 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 03 Mar 2009 05:19:08 -0800 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 03 Mar 2009 13:19:07 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id E3A382388995; Tue, 3 Mar 2009 13:18:46 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r749610 - in /ant/core/trunk/src: main/org/apache/tools/zip/ tests/junit/org/apache/tools/zip/ Date: Tue, 03 Mar 2009 13:18:46 -0000 To: notifications@ant.apache.org From: bodewig@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20090303131846.E3A382388995@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: bodewig Date: Tue Mar 3 13:18:45 2009 New Revision: 749610 URL: http://svn.apache.org/viewvc?rev=749610&view=rev Log: Parse central directory part of ZIP extra fields. PR 46637 Added: ant/core/trunk/src/main/org/apache/tools/zip/CentralDirectoryParsingZipExtraField.java (with props) Modified: ant/core/trunk/src/main/org/apache/tools/zip/ExtraFieldUtils.java (contents, props changed) ant/core/trunk/src/main/org/apache/tools/zip/UnrecognizedExtraField.java (contents, props changed) ant/core/trunk/src/main/org/apache/tools/zip/ZipEntry.java (contents, props changed) ant/core/trunk/src/main/org/apache/tools/zip/ZipFile.java (contents, props changed) ant/core/trunk/src/tests/junit/org/apache/tools/zip/ZipEntryTest.java (contents, props changed) Added: ant/core/trunk/src/main/org/apache/tools/zip/CentralDirectoryParsingZipExtraField.java URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/zip/CentralDirectoryParsingZipExtraField.java?rev=749610&view=auto ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/zip/CentralDirectoryParsingZipExtraField.java (added) +++ ant/core/trunk/src/main/org/apache/tools/zip/CentralDirectoryParsingZipExtraField.java Tue Mar 3 13:18:45 2009 @@ -0,0 +1,40 @@ +/* + * 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.tools.zip; + +import java.util.zip.ZipException; + +/** + * {@link ZipExtraField ZipExtraField} that knows how to parse central + * directory data. + * + * @since Ant 1.8.0 + */ +public interface CentralDirectoryParsingZipExtraField extends ZipExtraField { + /** + * Populate data from this array as if it was in central directory data. + * @param data an array of bytes + * @param offset the start offset + * @param length the number of bytes in the array from offset + * + * @throws ZipException on error + */ + void parseFromCentralDirectoryData(byte[] data, int offset, int length) + throws ZipException; +} Propchange: ant/core/trunk/src/main/org/apache/tools/zip/CentralDirectoryParsingZipExtraField.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: ant/core/trunk/src/main/org/apache/tools/zip/ExtraFieldUtils.java URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/zip/ExtraFieldUtils.java?rev=749610&r1=749609&r2=749610&view=diff ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/zip/ExtraFieldUtils.java (original) +++ ant/core/trunk/src/main/org/apache/tools/zip/ExtraFieldUtils.java Tue Mar 3 13:18:45 2009 @@ -92,13 +92,27 @@ /** * Split the array into ExtraFields and populate them with the - * give data. + * given data as local file data. + * @param data an array of bytes as it appears in local file data + * @return an array of ExtraFields + * @throws ZipException on error + */ + public static ZipExtraField[] parse(byte[] data) throws ZipException { + return parse(data, true); + } + + /** + * Split the array into ExtraFields and populate them with the + * given data. * @param data an array of bytes + * @param local whether data originates from the local file data + * or the central directory * @return an array of ExtraFields * @since 1.1 * @throws ZipException on error */ - public static ZipExtraField[] parse(byte[] data) throws ZipException { + public static ZipExtraField[] parse(byte[] data, boolean local) + throws ZipException { List v = new ArrayList(); int start = 0; while (start <= data.length - WORD) { @@ -110,7 +124,14 @@ } try { ZipExtraField ze = createExtraField(headerId); - ze.parseFromLocalFileData(data, start + WORD, length); + if (local + || !(ze instanceof CentralDirectoryParsingZipExtraField)) { + ze.parseFromLocalFileData(data, start + WORD, length); + } else { + ((CentralDirectoryParsingZipExtraField) ze) + .parseFromCentralDirectoryData(data, start + WORD, + length); + } v.add(ze); } catch (InstantiationException ie) { throw new ZipException(ie.getMessage()); Propchange: ant/core/trunk/src/main/org/apache/tools/zip/ExtraFieldUtils.java ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Tue Mar 3 13:18:45 2009 @@ -1 +1 @@ -/commons/sandbox/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ExtraFieldUtils.java:745528,746933,748133,749524 +/commons/sandbox/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ExtraFieldUtils.java:745528,746933,748133,749524,749603 Modified: ant/core/trunk/src/main/org/apache/tools/zip/UnrecognizedExtraField.java URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/zip/UnrecognizedExtraField.java?rev=749610&r1=749609&r2=749610&view=diff ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/zip/UnrecognizedExtraField.java (original) +++ ant/core/trunk/src/main/org/apache/tools/zip/UnrecognizedExtraField.java Tue Mar 3 13:18:45 2009 @@ -26,7 +26,8 @@ * identical - unless told the opposite.

* */ -public class UnrecognizedExtraField implements ZipExtraField { +public class UnrecognizedExtraField + implements CentralDirectoryParsingZipExtraField { /** * The Header-ID. @@ -135,6 +136,22 @@ setLocalFileDataData(tmp); } + /** + * @param data the array of bytes. + * @param offset the source location in the data array. + * @param length the number of bytes to use in the data array. + * @see ZipExtraField#parseFromCentralDirectoryData(byte[], int, int) + */ + public void parseFromCentralDirectoryData(byte[] data, int offset, + int length) { + byte[] tmp = new byte[length]; + System.arraycopy(data, offset, tmp, 0, length); + setCentralDirectoryData(tmp); + if (localData == null) { + setLocalFileDataData(tmp); + } + } + private static byte[] copy(byte[] from) { if (from != null) { byte[] to = new byte[from.length]; Propchange: ant/core/trunk/src/main/org/apache/tools/zip/UnrecognizedExtraField.java ------------------------------------------------------------------------------ --- svn:mergeinfo (added) +++ svn:mergeinfo Tue Mar 3 13:18:45 2009 @@ -0,0 +1 @@ +/commons/sandbox/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/UnrecognizedExtraField.java:746933,748133,749603 Modified: ant/core/trunk/src/main/org/apache/tools/zip/ZipEntry.java URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/zip/ZipEntry.java?rev=749610&r1=749609&r2=749610&view=diff ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/zip/ZipEntry.java (original) +++ ant/core/trunk/src/main/org/apache/tools/zip/ZipEntry.java Tue Mar 3 13:18:45 2009 @@ -284,7 +284,8 @@ */ public void setExtra(byte[] extra) throws RuntimeException { try { - setExtraFields(ExtraFieldUtils.parse(extra)); + ZipExtraField[] local = ExtraFieldUtils.parse(extra, true); + mergeExtraFields(local, true); } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } @@ -303,6 +304,18 @@ } /** + * Sets the central directory part of extra fields. + */ + public void setCentralDirectoryExtra(byte[] b) { + try { + ZipExtraField[] central = ExtraFieldUtils.parse(b, false); + mergeExtraFields(central, false); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + /** * Retrieves the extra data for the local file data. * @return the extra data for local file * @since 1.1 @@ -386,4 +399,37 @@ return (this == o); } + /** + * If there are no extra fields, use the given fields as new extra + * data - otherwise merge the fields assuming the existing fields + * and the new fields stem from different locations inside the + * archive. + * @param f the extra fields to merge + * @param local whether the new fields originate from local data + */ + private void mergeExtraFields(ZipExtraField[] f, boolean local) + throws ZipException { + if (extraFields == null) { + setExtraFields(f); + } else { + for (int i = 0; i < f.length; i++) { + ZipExtraField existing = getExtraField(f[i].getHeaderId()); + if (existing == null) { + addExtraField(f[i]); + } else { + if (local + || !(existing + instanceof CentralDirectoryParsingZipExtraField)) { + byte[] b = f[i].getLocalFileDataData(); + existing.parseFromLocalFileData(b, 0, b.length); + } else { + byte[] b = f[i].getCentralDirectoryData(); + ((CentralDirectoryParsingZipExtraField) existing) + .parseFromCentralDirectoryData(b, 0, b.length); + } + } + } + setExtra(); + } + } } Propchange: ant/core/trunk/src/main/org/apache/tools/zip/ZipEntry.java ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Tue Mar 3 13:18:45 2009 @@ -1,2 +1,2 @@ -/commons/sandbox/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveEntry.java:747850 +/commons/sandbox/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveEntry.java:747850,749603 /commons/sandbox/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipEntry.java:746933,748133,749524 Modified: ant/core/trunk/src/main/org/apache/tools/zip/ZipFile.java URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/zip/ZipFile.java?rev=749610&r1=749609&r2=749610&view=diff ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/zip/ZipFile.java (original) +++ ant/core/trunk/src/main/org/apache/tools/zip/ZipFile.java Tue Mar 3 13:18:45 2009 @@ -389,15 +389,9 @@ nameMap.put(ze.getName(), ze); - int lenToSkip = extraLen; - while (lenToSkip > 0) { - int skipped = archive.skipBytes(lenToSkip); - if (skipped <= 0) { - throw new RuntimeException("failed to skip extra data in" - + " central directory"); - } - lenToSkip -= skipped; - } + byte[] cdExtraData = new byte[extraLen]; + archive.readFully(cdExtraData); + ze.setCentralDirectoryExtra(cdExtraData); byte[] comment = new byte[commentLen]; archive.readFully(comment); Propchange: ant/core/trunk/src/main/org/apache/tools/zip/ZipFile.java ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Tue Mar 3 13:18:45 2009 @@ -1 +1 @@ -/commons/sandbox/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java:745920,746933,748133,748556,749342-749344,749524 +/commons/sandbox/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java:745920,746933,748133,748556,749342-749344,749524,749603 Modified: ant/core/trunk/src/tests/junit/org/apache/tools/zip/ZipEntryTest.java URL: http://svn.apache.org/viewvc/ant/core/trunk/src/tests/junit/org/apache/tools/zip/ZipEntryTest.java?rev=749610&r1=749609&r2=749610&view=diff ============================================================================== --- ant/core/trunk/src/tests/junit/org/apache/tools/zip/ZipEntryTest.java (original) +++ ant/core/trunk/src/tests/junit/org/apache/tools/zip/ZipEntryTest.java Tue Mar 3 13:18:45 2009 @@ -32,8 +32,6 @@ /** * test handling of extra fields - * - * @since 1.1 */ public void testExtraFields() { AsiExtraField a = new AsiExtraField(); @@ -86,9 +84,51 @@ } /** + * test handling of extra fields via central directory + */ + public void testExtraFieldMerging() { + AsiExtraField a = new AsiExtraField(); + a.setDirectory(true); + a.setMode(0755); + UnrecognizedExtraField u = new UnrecognizedExtraField(); + u.setHeaderId(new ZipShort(1)); + u.setLocalFileDataData(new byte[0]); + + ZipEntry ze = new ZipEntry("test/"); + ze.setExtraFields(new ZipExtraField[] {a, u}); + + // merge + // Header-ID 1 + length 1 + one byte of data + ze.setCentralDirectoryExtra(new byte[] {1, 0, 1, 0, 127}); + + ZipExtraField[] result = ze.getExtraFields(); + assertEquals("first pass", 2, result.length); + assertSame(a, result[0]); + assertEquals(new ZipShort(1), result[1].getHeaderId()); + assertEquals(new ZipShort(0), result[1].getLocalFileDataLength()); + assertEquals(new ZipShort(1), result[1].getCentralDirectoryLength()); + + // add new + // Header-ID 2 + length 0 + ze.setCentralDirectoryExtra(new byte[] {2, 0, 0, 0}); + + result = ze.getExtraFields(); + assertEquals("second pass", 3, result.length); + + // merge + // Header-ID 2 + length 1 + one byte of data + ze.setExtra(new byte[] {2, 0, 1, 0, 127}); + + result = ze.getExtraFields(); + assertEquals("third pass", 3, result.length); + assertSame(a, result[0]); + assertEquals(new ZipShort(2), result[2].getHeaderId()); + assertEquals(new ZipShort(1), result[2].getLocalFileDataLength()); + assertEquals(new ZipShort(0), result[2].getCentralDirectoryLength()); + } + + /** * test handling of extra fields - * - * @since 1.1 */ public void testAddAsFirstExtraField() { AsiExtraField a = new AsiExtraField(); Propchange: ant/core/trunk/src/tests/junit/org/apache/tools/zip/ZipEntryTest.java ------------------------------------------------------------------------------ --- svn:mergeinfo (added) +++ svn:mergeinfo Tue Mar 3 13:18:45 2009 @@ -0,0 +1 @@ +/commons/sandbox/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/ZipArchiveEntryTest.java:749603