/* * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * This source code is provided to illustrate the usage of a given feature * or technique and has been deliberately simplified. Additional steps * required for a production-quality application, such as security checks, * input validation and proper error handling, might not be present in * this sample code. */ package com.sun.nio.zipfs; import java.nio.file.Paths; import java.util.Collections; import java.util.Map; import static com.sun.nio.zipfs.ZipConstants.*; import static com.sun.nio.zipfs.ZipUtils.*; /** * Print all loc and cen headers of the ZIP file * * @author Xueming Shen */ public class ZipInfo { public static void main(String[] args) throws Throwable { if (args.length < 1) { print("Usage: java ZipInfo zfname"); } else { Map<String, ?> env = Collections.emptyMap(); ZipFileSystem zfs = (ZipFileSystem)(new ZipFileSystemProvider() .newFileSystem(Paths.get(args[0]), env)); byte[] cen = zfs.cen; if (cen == null) { print("zip file is empty%n"); return; } int pos = 0; byte[] buf = new byte[1024]; int no = 1; while (pos + CENHDR < cen.length) { print("----------------#%d--------------------%n", no++); printCEN(cen, pos); // use size CENHDR as the extra bytes to read, just in case the // loc.extra is bigger than the cen.extra, try to avoid to read // twice long len = LOCHDR + CENNAM(cen, pos) + CENEXT(cen, pos) + CENHDR; if (zfs.readFullyAt(buf, 0, len, locoff(cen, pos)) != len) ZipFileSystem.zerror("read loc header failed"); if (LOCEXT(buf) > CENEXT(cen, pos) + CENHDR) { // have to read the second time; len = LOCHDR + LOCNAM(buf) + LOCEXT(buf); if (zfs.readFullyAt(buf, 0, len, locoff(cen, pos)) != len) ZipFileSystem.zerror("read loc header failed"); } printLOC(buf); pos += CENHDR + CENNAM(cen, pos) + CENEXT(cen, pos) + CENCOM(cen, pos); } zfs.close(); } } static void print(String fmt, Object... objs) { System.out.printf(fmt, objs); } static void printLOC(byte[] loc) { print("%n"); print("[Local File Header]%n"); print(" Signature : %#010x%n", LOCSIG(loc)); if (LOCSIG(loc) != LOCSIG) { print(" Wrong signature!"); return; } print(" Version : %#6x [%d.%d]%n", LOCVER(loc), LOCVER(loc) / 10, LOCVER(loc) % 10); print(" Flag : %#6x%n", LOCFLG(loc)); print(" Method : %#6x%n", LOCHOW(loc)); print(" LastMTime : %#10x [%tc]%n", LOCTIM(loc), dosToJavaTime(LOCTIM(loc))); print(" CRC : %#10x%n", LOCCRC(loc)); print(" CSize : %#10x%n", LOCSIZ(loc)); print(" Size : %#10x%n", LOCLEN(loc)); print(" NameLength : %#6x [%s]%n", LOCNAM(loc), new String(loc, LOCHDR, LOCNAM(loc))); print(" ExtraLength : %#6x%n", LOCEXT(loc)); if (LOCEXT(loc) != 0) printExtra(loc, LOCHDR + LOCNAM(loc), LOCEXT(loc)); } static void printCEN(byte[] cen, int off) { print("[Central Directory Header]%n"); print(" Signature : %#010x%n", CENSIG(cen, off)); if (CENSIG(cen, off) != CENSIG) { print(" Wrong signature!"); return; } print(" VerMadeby : %#6x [%d, %d.%d]%n", CENVEM(cen, off), (CENVEM(cen, off) >> 8), (CENVEM(cen, off) & 0xff) / 10, (CENVEM(cen, off) & 0xff) % 10); print(" VerExtract : %#6x [%d.%d]%n", CENVER(cen, off), CENVER(cen, off) / 10, CENVER(cen, off) % 10); print(" Flag : %#6x%n", CENFLG(cen, off)); print(" Method : %#6x%n", CENHOW(cen, off)); print(" LastMTime : %#10x [%tc]%n", CENTIM(cen, off), dosToJavaTime(CENTIM(cen, off))); print(" CRC : %#10x%n", CENCRC(cen, off)); print(" CSize : %#10x%n", CENSIZ(cen, off)); print(" Size : %#10x%n", CENLEN(cen, off)); print(" NameLen : %#6x [%s]%n", CENNAM(cen, off), new String(cen, off + CENHDR, CENNAM(cen, off))); print(" ExtraLen : %#6x%n", CENEXT(cen, off)); if (CENEXT(cen, off) != 0) printExtra(cen, off + CENHDR + CENNAM(cen, off), CENEXT(cen, off)); print(" CommentLen : %#6x%n", CENCOM(cen, off)); print(" DiskStart : %#6x%n", CENDSK(cen, off)); print(" Attrs : %#6x%n", CENATT(cen, off)); print(" AttrsEx : %#10x%n", CENATX(cen, off)); print(" LocOff : %#10x%n", CENOFF(cen, off)); } static long locoff(byte[] cen, int pos) { long locoff = CENOFF(cen, pos); if (locoff == ZIP64_MINVAL) { //ZIP64 int off = pos + CENHDR + CENNAM(cen, pos); int end = off + CENEXT(cen, pos); while (off + 4 < end) { int tag = SH(cen, off); int sz = SH(cen, off + 2); if (tag != EXTID_ZIP64) { off += 4 + sz; continue; } off += 4; if (CENLEN(cen, pos) == ZIP64_MINVAL) off += 8; if (CENSIZ(cen, pos) == ZIP64_MINVAL) off += 8; return LL(cen, off); } // should never be here } return locoff; } static void printExtra(byte[] extra, int off, int len) { int end = off + len; while (off + 4 <= end) { int tag = SH(extra, off); int sz = SH(extra, off + 2); print(" [tag=0x%04x, sz=%d, data= ", tag, sz); if (off + sz > end) { print(" Error: Invalid extra data, beyond extra length"); break; } off += 4; for (int i = 0; i < sz; i++) print("%02x ", extra[off + i]); print("]%n"); switch (tag) { case EXTID_ZIP64 : print(" ->ZIP64: "); int pos = off; while (pos + 8 <= off + sz) { print(" *0x%x ", LL(extra, pos)); pos += 8; } print("%n"); break; case EXTID_NTFS: print(" ->PKWare NTFS%n"); // 4 bytes reserved if (SH(extra, off + 4) != 0x0001 || SH(extra, off + 6) != 24) print(" Error: Invalid NTFS sub-tag or subsz"); print(" mtime:%tc%n", winToJavaTime(LL(extra, off + 8))); print(" atime:%tc%n", winToJavaTime(LL(extra, off + 16))); print(" ctime:%tc%n", winToJavaTime(LL(extra, off + 24))); break; case EXTID_EXTT: print(" ->Info-ZIP Extended Timestamp: flag=%x%n",extra[off]); pos = off + 1 ; while (pos + 4 <= off + sz) { print(" *%tc%n", unixToJavaTime(LG(extra, pos))); pos += 4; } break; default: print(" ->[tag=%x, size=%d]%n", tag, sz); } off += sz; } } }