151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/* 2f54e9b2a5f66f0caa1ae89e15ed0a26d00795df1Przemyslaw Szczepaniak * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. 351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it 651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as 751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation. Oracle designates this 851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided 951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code. 1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT 1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that 1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code). 1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version 1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation, 1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any 2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions. 2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage java.util.zip; 2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.nio.ByteBuffer; 2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.nio.CharBuffer; 3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.nio.charset.Charset; 3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.nio.charset.StandardCharsets; 3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.nio.charset.CharsetDecoder; 3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.nio.charset.CharsetEncoder; 3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.nio.charset.CoderResult; 3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.nio.charset.CodingErrorAction; 3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Arrays; 3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.nio.cs.ArrayDecoder; 3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.nio.cs.ArrayEncoder; 3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/** 4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Utility class for zipfile name and comment decoding and encoding 4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskifinal class ZipCoder { 4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String toString(byte[] ba, int length) { 4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski CharsetDecoder cd = decoder().reset(); 4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int len = (int)(length * cd.maxCharsPerByte()); 4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char[] ca = new char[len]; 5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len == 0) 5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new String(ca); 5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // UTF-8 only for now. Other ArrayDeocder only handles 5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // CodingErrorAction.REPLACE mode. ZipCoder uses 5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // REPORT mode. 5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (isUTF8 && cd instanceof ArrayDecoder) { 5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int clen = ((ArrayDecoder)cd).decode(ba, 0, length, ca); 5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (clen == -1) // malformed 5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException("MALFORMED"); 5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new String(ca, 0, clen); 6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ByteBuffer bb = ByteBuffer.wrap(ba, 0, length); 6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski CharBuffer cb = CharBuffer.wrap(ca); 6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski CoderResult cr = cd.decode(bb, cb, true); 6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!cr.isUnderflow()) 6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException(cr.toString()); 6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski cr = cd.flush(cb); 6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!cr.isUnderflow()) 6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException(cr.toString()); 6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new String(ca, 0, cb.position()); 7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String toString(byte[] ba) { 7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return toString(ba, ba.length); 7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] getBytes(String s) { 7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski CharsetEncoder ce = encoder().reset(); 7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski char[] ca = s.toCharArray(); 7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int len = (int)(ca.length * ce.maxBytesPerChar()); 8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] ba = new byte[len]; 8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len == 0) 8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return ba; 8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // UTF-8 only for now. Other ArrayDeocder only handles 8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // CodingErrorAction.REPLACE mode. 8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (isUTF8 && ce instanceof ArrayEncoder) { 8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int blen = ((ArrayEncoder)ce).encode(ca, 0, ca.length, ba); 8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (blen == -1) // malformed 8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException("MALFORMED"); 8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return Arrays.copyOf(ba, blen); 9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ByteBuffer bb = ByteBuffer.wrap(ba); 9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski CharBuffer cb = CharBuffer.wrap(ca); 9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski CoderResult cr = ce.encode(cb, bb, true); 9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!cr.isUnderflow()) 9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException(cr.toString()); 9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski cr = ce.flush(bb); 9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!cr.isUnderflow()) 9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException(cr.toString()); 9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (bb.position() == ba.length) // defensive copy? 10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return ba; 10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski else 10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return Arrays.copyOf(ba, bb.position()); 10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // assume invoked only if "this" is not utf8 10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] getBytesUTF8(String s) { 10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (isUTF8) 10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return getBytes(s); 10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (utf8 == null) 11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski utf8 = new ZipCoder(StandardCharsets.UTF_8); 11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return utf8.getBytes(s); 11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String toStringUTF8(byte[] ba, int len) { 11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (isUTF8) 11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return toString(ba, len); 11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (utf8 == null) 11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski utf8 = new ZipCoder(StandardCharsets.UTF_8); 12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return utf8.toString(ba, len); 12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski boolean isUTF8() { 12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return isUTF8; 12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private Charset cs; 12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private CharsetDecoder dec; 12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private CharsetEncoder enc; 13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private boolean isUTF8; 13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private ZipCoder utf8; 13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private ZipCoder(Charset cs) { 13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.cs = cs; 13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.isUTF8 = cs.name().equals(StandardCharsets.UTF_8.name()); 13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski static ZipCoder get(Charset charset) { 13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new ZipCoder(charset); 14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private CharsetDecoder decoder() { 14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (dec == null) { 14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dec = cs.newDecoder() 14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski .onMalformedInput(CodingErrorAction.REPORT) 14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski .onUnmappableCharacter(CodingErrorAction.REPORT); 14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return dec; 14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private CharsetEncoder encoder() { 15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (enc == null) { 15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski enc = cs.newEncoder() 15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski .onMalformedInput(CodingErrorAction.REPORT) 15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski .onUnmappableCharacter(CodingErrorAction.REPORT); 15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return enc; 15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski} 160