jaroslav@705: /* jaroslav@705: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. jaroslav@705: * jaroslav@705: * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. jaroslav@705: * jaroslav@705: * Oracle and Java are registered trademarks of Oracle and/or its affiliates. jaroslav@705: * Other names may be trademarks of their respective owners. jaroslav@705: * jaroslav@705: * The contents of this file are subject to the terms of either the GNU jaroslav@705: * General Public License Version 2 only ("GPL") or the Common jaroslav@705: * Development and Distribution License("CDDL") (collectively, the jaroslav@705: * "License"). You may not use this file except in compliance with the jaroslav@705: * License. You can obtain a copy of the License at jaroslav@705: * http://www.netbeans.org/cddl-gplv2.html jaroslav@705: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the jaroslav@705: * specific language governing permissions and limitations under the jaroslav@705: * License. When distributing the software, include this License Header jaroslav@705: * Notice in each file and include the License file at jaroslav@705: * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this jaroslav@705: * particular file as subject to the "Classpath" exception as provided jaroslav@705: * by Oracle in the GPL Version 2 section of the License file that jaroslav@705: * accompanied this code. If applicable, add the following below the jaroslav@705: * License Header, with the fields enclosed by brackets [] replaced by jaroslav@705: * your own identifying information: jaroslav@705: * "Portions Copyrighted [year] [name of copyright owner]" jaroslav@705: * jaroslav@705: * Contributor(s): jaroslav@705: * jaroslav@705: * Portions Copyrighted 2007 Sun Microsystems, Inc. jaroslav@705: */ jaroslav@706: package org.apidesign.bck2brwsr.emul.zip; jaroslav@705: jaroslav@706: import java.io.ByteArrayInputStream; jaroslav@705: import java.io.IOException; jaroslav@705: import java.io.InputStream; jaroslav@705: import java.util.zip.ZipEntry; jaroslav@705: import java.util.zip.ZipInputStream; jaroslav@705: jaroslav@705: /** jaroslav@705: * jaroslav@705: * @author Tomas Zezula jaroslav@705: */ jaroslav@705: public final class FastJar { jaroslav@706: private final byte[] arr; jaroslav@705: jaroslav@706: public FastJar(byte[] arr) { jaroslav@706: this.arr = arr; jaroslav@705: } jaroslav@705: jaroslav@705: jaroslav@705: private static final int GIVE_UP = 1<<16; jaroslav@705: jaroslav@705: public static final class Entry { jaroslav@705: jaroslav@705: public final String name; jaroslav@705: final long offset; jaroslav@705: private final long dosTime; jaroslav@705: jaroslav@706: Entry (String name, long offset, long time) { jaroslav@705: assert name != null; jaroslav@705: this.name = name; jaroslav@705: this.offset = offset; jaroslav@705: this.dosTime = time; jaroslav@705: } jaroslav@706: /* jaroslav@705: public long getTime () { jaroslav@705: Date d = new Date((int)(((dosTime >> 25) & 0x7f) + 80), jaroslav@705: (int)(((dosTime >> 21) & 0x0f) - 1), jaroslav@705: (int)((dosTime >> 16) & 0x1f), jaroslav@705: (int)((dosTime >> 11) & 0x1f), jaroslav@705: (int)((dosTime >> 5) & 0x3f), jaroslav@705: (int)((dosTime << 1) & 0x3e)); jaroslav@705: return d.getTime(); jaroslav@705: } jaroslav@706: */ jaroslav@705: } jaroslav@705: jaroslav@706: public InputStream getInputStream (final Entry e) throws IOException { jaroslav@706: return getInputStream(arr, e.offset); jaroslav@705: } jaroslav@705: jaroslav@706: private static InputStream getInputStream (byte[] arr, final long offset) throws IOException { jaroslav@706: ByteArrayInputStream is = new ByteArrayInputStream(arr); jaroslav@706: is.skip(offset); jaroslav@706: ZipInputStream in = new ZipInputStream (is); jaroslav@705: ZipEntry e = in.getNextEntry(); jaroslav@705: if (e != null && e.getCrc() == 0L && e.getMethod() == ZipEntry.STORED) { jaroslav@706: int cp = arr.length - is.available(); jaroslav@706: return new ByteArrayInputStream(arr, cp, (int)e.getSize()); jaroslav@705: } jaroslav@705: return in; jaroslav@705: } jaroslav@705: jaroslav@706: public Entry[] list() throws IOException { jaroslav@706: final int size = arr.length; jaroslav@706: jaroslav@706: int at = size - ZipInputStream.ENDHDR; jaroslav@706: jaroslav@706: byte[] data = new byte[ZipInputStream.ENDHDR]; jaroslav@706: int giveup = 0; jaroslav@706: jaroslav@706: do { jaroslav@706: org.apidesign.bck2brwsr.emul.lang.System.arraycopy(arr, at, data, 0, data.length); jaroslav@706: at--; jaroslav@706: giveup++; jaroslav@706: if (giveup > GIVE_UP) { jaroslav@706: throw new IOException (); jaroslav@705: } jaroslav@706: } while (getsig(data) != ZipInputStream.ENDSIG); jaroslav@706: jaroslav@706: jaroslav@706: final long censize = endsiz(data); jaroslav@706: final long cenoff = endoff(data); jaroslav@706: at = (int) cenoff; jaroslav@706: jaroslav@706: Entry[] result = new Entry[0]; jaroslav@706: int cenread = 0; jaroslav@706: data = new byte[ZipInputStream.CENHDR]; jaroslav@706: while (cenread < censize) { jaroslav@706: org.apidesign.bck2brwsr.emul.lang.System.arraycopy(arr, at, data, 0, data.length); jaroslav@706: at += data.length; jaroslav@706: if (getsig(data) != ZipInputStream.CENSIG) { jaroslav@706: throw new IOException("No central table"); //NOI18N jaroslav@706: } jaroslav@706: int cennam = cennam(data); jaroslav@706: int cenext = cenext(data); jaroslav@706: int cencom = cencom(data); jaroslav@706: long lhoff = cenoff(data); jaroslav@706: long centim = centim(data); jaroslav@706: String name = new String(arr, at, cennam, "UTF-8"); jaroslav@706: at += cennam; jaroslav@706: int seekby = cenext+cencom; jaroslav@706: int cendatalen = ZipInputStream.CENHDR + cennam + seekby; jaroslav@706: cenread+=cendatalen; jaroslav@706: result = addEntry(result, new Entry(name,lhoff, centim)); jaroslav@706: at += seekby; jaroslav@705: } jaroslav@706: return result; jaroslav@705: } jaroslav@705: jaroslav@706: private Entry[] addEntry(Entry[] result, Entry entry) { jaroslav@706: Entry[] e = new Entry[result.length + 1]; jaroslav@706: e[result.length] = entry; jaroslav@706: org.apidesign.bck2brwsr.emul.lang.System.arraycopy(result, 0, e, 0, result.length); jaroslav@706: return e; jaroslav@705: } jaroslav@705: jaroslav@705: private static final long getsig(final byte[] b) throws IOException {return get32(b,0);} jaroslav@706: private static final long endsiz(final byte[] b) throws IOException {return get32(b,ZipInputStream.ENDSIZ);} jaroslav@706: private static final long endoff(final byte[] b) throws IOException {return get32(b,ZipInputStream.ENDOFF);} jaroslav@706: private static final long cenlen(final byte[] b) throws IOException {return get32(b,ZipInputStream.CENLEN);} jaroslav@706: private static final long censiz(final byte[] b) throws IOException {return get32(b,ZipInputStream.CENSIZ);} jaroslav@706: private static final long centim(final byte[] b) throws IOException {return get32(b,ZipInputStream.CENTIM);} jaroslav@706: private static final int cennam(final byte[] b) throws IOException {return get16(b,ZipInputStream.CENNAM);} jaroslav@706: private static final int cenext(final byte[] b) throws IOException {return get16(b,ZipInputStream.CENEXT);} jaroslav@706: private static final int cencom(final byte[] b) throws IOException {return get16(b,ZipInputStream.CENCOM);} jaroslav@706: private static final long cenoff (final byte[] b) throws IOException {return get32(b,ZipInputStream.CENOFF);} jaroslav@706: private static final int lochow(final byte[] b) throws IOException {return get16(b,ZipInputStream.LOCHOW);} jaroslav@706: private static final int locname(final byte[] b) throws IOException {return get16(b,ZipInputStream.LOCNAM);} jaroslav@706: private static final int locext(final byte[] b) throws IOException {return get16(b,ZipInputStream.LOCEXT);} jaroslav@706: private static final long locsiz(final byte[] b) throws IOException {return get32(b,ZipInputStream.LOCSIZ);} jaroslav@705: jaroslav@705: private static final int get16(final byte[] b, int off) throws IOException { jaroslav@705: final int b1 = b[off]; jaroslav@705: final int b2 = b[off+1]; jaroslav@705: return (b1 & 0xff) | ((b2 & 0xff) << 8); jaroslav@705: } jaroslav@705: jaroslav@705: private static final long get32(final byte[] b, int off) throws IOException { jaroslav@705: final int s1 = get16(b, off); jaroslav@705: final int s2 = get16(b, off+2); jaroslav@705: return s1 | ((long)s2 << 16); jaroslav@705: } jaroslav@705: jaroslav@705: }