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