All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.tools.zip.ZipUtil Maven / Gradle / Ivy

There is a newer version: 1.10.15
Show newest version
/*
 *  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.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.zip.CRC32;

/**
 * Utility class for handling DOS and Java time conversions.
 * @since Ant 1.8.1
 */
public abstract class ZipUtil {
    /**
     * Smallest date/time ZIP can handle.
     */
    private static final byte[] DOS_TIME_MIN = ZipLong.getBytes(0x00002100L);

    /**
     * Convert a Date object to a DOS date/time field.
     * @param time the Date to convert
     * @return the date as a ZipLong
     */
    public static ZipLong toDosTime(Date time) {
        return new ZipLong(toDosTime(time.getTime()));
    }

    /**
     * Convert a Date object to a DOS date/time field.
     *
     * 

Stolen from InfoZip's fileio.c

* @param t number of milliseconds since the epoch * @return the date as a byte array */ public static byte[] toDosTime(long t) { byte[] result = new byte[4]; toDosTime(t, result, 0); return result; } /** * Convert a Date object to a DOS date/time field. * *

Stolen from InfoZip's fileio.c

* @param t number of milliseconds since the epoch * @param buf the output buffer * @param offset * The offset within the output buffer of the first byte to be written. * must be non-negative and no larger than buf.length-4 */ public static void toDosTime(long t, byte[] buf, int offset) { toDosTime(Calendar.getInstance(), t, buf, offset); } static void toDosTime(Calendar c, long t, byte[] buf, int offset) { c.setTimeInMillis(t); int year = c.get(Calendar.YEAR); if (year < 1980) { System.arraycopy(DOS_TIME_MIN, 0, buf, offset, DOS_TIME_MIN.length);// stop callers from changing the array return; } int month = c.get(Calendar.MONTH) + 1; long value = ((year - 1980) << 25) | (month << 21) | (c.get(Calendar.DAY_OF_MONTH) << 16) | (c.get(Calendar.HOUR_OF_DAY) << 11) | (c.get(Calendar.MINUTE) << 5) | (c.get(Calendar.SECOND) >> 1); ZipLong.putLong(value, buf, offset); } /** * Assumes a negative integer really is a positive integer that * has wrapped around and re-creates the original value. * *

This methods is no longer used as of Apache Ant 1.9.0

* * @param i the value to treat as unsigned int. * @return the unsigned int as a long. */ public static long adjustToLong(int i) { if (i < 0) { return 2 * ((long) Integer.MAX_VALUE) + 2 + i; } else { return i; } } /** * Convert a DOS date/time field to a Date object. * * @param zipDosTime contains the stored DOS time. * @return a Date instance corresponding to the given time. */ public static Date fromDosTime(ZipLong zipDosTime) { long dosTime = zipDosTime.getValue(); return new Date(dosToJavaTime(dosTime)); } /** * Converts DOS time to Java time (number of milliseconds since * epoch). */ public static long dosToJavaTime(long dosTime) { Calendar cal = Calendar.getInstance(); // CheckStyle:MagicNumberCheck OFF - no point cal.set(Calendar.YEAR, (int) ((dosTime >> 25) & 0x7f) + 1980); cal.set(Calendar.MONTH, (int) ((dosTime >> 21) & 0x0f) - 1); cal.set(Calendar.DATE, (int) (dosTime >> 16) & 0x1f); cal.set(Calendar.HOUR_OF_DAY, (int) (dosTime >> 11) & 0x1f); cal.set(Calendar.MINUTE, (int) (dosTime >> 5) & 0x3f); cal.set(Calendar.SECOND, (int) (dosTime << 1) & 0x3e); cal.set(Calendar.MILLISECOND, 0); // CheckStyle:MagicNumberCheck ON return cal.getTime().getTime(); } /** * If the entry has Unicode*ExtraFields and the CRCs of the * names/comments match those of the extra fields, transfer the * known Unicode values from the extra field. */ static void setNameAndCommentFromExtraFields(ZipEntry ze, byte[] originalNameBytes, byte[] commentBytes) { UnicodePathExtraField name = (UnicodePathExtraField) ze.getExtraField(UnicodePathExtraField.UPATH_ID); String originalName = ze.getName(); String newName = getUnicodeStringIfOriginalMatches(name, originalNameBytes); if (newName != null && !originalName.equals(newName)) { ze.setName(newName); } if (commentBytes != null && commentBytes.length > 0) { UnicodeCommentExtraField cmt = (UnicodeCommentExtraField) ze.getExtraField(UnicodeCommentExtraField.UCOM_ID); String newComment = getUnicodeStringIfOriginalMatches(cmt, commentBytes); if (newComment != null) { ze.setComment(newComment); } } } /** * If the stored CRC matches the one of the given name, return the * Unicode name of the given field. * *

If the field is null or the CRCs don't match, return null * instead.

*/ private static String getUnicodeStringIfOriginalMatches(AbstractUnicodeExtraField f, byte[] orig) { if (f != null) { CRC32 crc32 = new CRC32(); crc32.update(orig); long origCRC32 = crc32.getValue(); if (origCRC32 == f.getNameCRC32()) { try { return ZipEncodingHelper .UTF8_ZIP_ENCODING.decode(f.getUnicodeName()); } catch (IOException ex) { // UTF-8 unsupported? should be impossible the // Unicode*ExtraField must contain some bad bytes // TODO log this anywhere? return null; } } } return null; } /** * Create a copy of the given array - or return null if the * argument is null. */ static byte[] copy(byte[] from) { if (from != null) { byte[] to = new byte[from.length]; System.arraycopy(from, 0, to, 0, to.length); return to; } return null; } /** * Whether this library is able to read or write the given entry. */ static boolean canHandleEntryData(ZipEntry entry) { return supportsEncryptionOf(entry) && supportsMethodOf(entry); } /** * Whether this library supports the encryption used by the given * entry. * * @return true if the entry isn't encrypted at all */ private static boolean supportsEncryptionOf(ZipEntry entry) { return !entry.getGeneralPurposeBit().usesEncryption(); } /** * Whether this library supports the compression method used by * the given entry. * * @return true if the compression method is STORED or DEFLATED */ private static boolean supportsMethodOf(ZipEntry entry) { return entry.getMethod() == ZipEntry.STORED || entry.getMethod() == ZipEntry.DEFLATED; } /** * Checks whether the entry requires features not (yet) supported * by the library and throws an exception if it does. */ static void checkRequestedFeatures(ZipEntry ze) throws UnsupportedZipFeatureException { if (!supportsEncryptionOf(ze)) { throw new UnsupportedZipFeatureException(UnsupportedZipFeatureException .Feature.ENCRYPTION, ze); } if (!supportsMethodOf(ze)) { throw new UnsupportedZipFeatureException(UnsupportedZipFeatureException .Feature.METHOD, ze); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy