1 /* 2 * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * - Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 11 * - Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * - Neither the name of Oracle nor the names of its 16 * contributors may be used to endorse or promote products derived 17 * from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 20 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * This source code is provided to illustrate the usage of a given feature 34 * or technique and has been deliberately simplified. Additional steps 35 * required for a production-quality application, such as security checks, 36 * input validation and proper error handling, might not be present in 37 * this sample code. 38 */ 39 40 41 package com.sun.nio.zipfs; 42 43 import java.nio.file.Paths; 44 import java.util.Collections; 45 import java.util.Map; 46 import static com.sun.nio.zipfs.ZipConstants.*; 47 import static com.sun.nio.zipfs.ZipUtils.*; 48 49 /** 50 * Print all loc and cen headers of the ZIP file 51 * 52 * @author Xueming Shen 53 */ 54 55 public class ZipInfo { 56 57 public static void main(String[] args) throws Throwable { 58 if (args.length < 1) { 59 print("Usage: java ZipInfo zfname"); 60 } else { 61 Map<String, ?> env = Collections.emptyMap(); 62 ZipFileSystem zfs = (ZipFileSystem)(new ZipFileSystemProvider() 63 .newFileSystem(Paths.get(args[0]), env)); 64 byte[] cen = zfs.cen; 65 if (cen == null) { 66 print("zip file is empty%n"); 67 return; 68 } 69 int pos = 0; 70 byte[] buf = new byte[1024]; 71 int no = 1; 72 while (pos + CENHDR < cen.length) { 73 print("----------------#%d--------------------%n", no++); 74 printCEN(cen, pos); 75 76 // use size CENHDR as the extra bytes to read, just in case the 77 // loc.extra is bigger than the cen.extra, try to avoid to read 78 // twice 79 long len = LOCHDR + CENNAM(cen, pos) + CENEXT(cen, pos) + CENHDR; 80 if (zfs.readFullyAt(buf, 0, len, locoff(cen, pos)) != len) 81 ZipFileSystem.zerror("read loc header failed"); 82 if (LOCEXT(buf) > CENEXT(cen, pos) + CENHDR) { 83 // have to read the second time; 84 len = LOCHDR + LOCNAM(buf) + LOCEXT(buf); 85 if (zfs.readFullyAt(buf, 0, len, locoff(cen, pos)) != len) 86 ZipFileSystem.zerror("read loc header failed"); 87 } 88 printLOC(buf); 89 pos += CENHDR + CENNAM(cen, pos) + CENEXT(cen, pos) + CENCOM(cen, pos); 90 } 91 zfs.close(); 92 } 93 } 94 95 static void print(String fmt, Object... objs) { 96 System.out.printf(fmt, objs); 97 } 98 99 static void printLOC(byte[] loc) { 100 print("%n"); 101 print("[Local File Header]%n"); 102 print(" Signature : %#010x%n", LOCSIG(loc)); 103 if (LOCSIG(loc) != LOCSIG) { 104 print(" Wrong signature!"); 105 return; 106 } 107 print(" Version : %#6x [%d.%d]%n", 108 LOCVER(loc), LOCVER(loc) / 10, LOCVER(loc) % 10); 109 print(" Flag : %#6x%n", LOCFLG(loc)); 110 print(" Method : %#6x%n", LOCHOW(loc)); 111 print(" LastMTime : %#10x [%tc]%n", 112 LOCTIM(loc), dosToJavaTime(LOCTIM(loc))); 113 print(" CRC : %#10x%n", LOCCRC(loc)); 114 print(" CSize : %#10x%n", LOCSIZ(loc)); 115 print(" Size : %#10x%n", LOCLEN(loc)); 116 print(" NameLength : %#6x [%s]%n", 117 LOCNAM(loc), new String(loc, LOCHDR, LOCNAM(loc))); 118 print(" ExtraLength : %#6x%n", LOCEXT(loc)); 119 if (LOCEXT(loc) != 0) 120 printExtra(loc, LOCHDR + LOCNAM(loc), LOCEXT(loc)); 121 } 122 123 static void printCEN(byte[] cen, int off) { 124 print("[Central Directory Header]%n"); 125 print(" Signature : %#010x%n", CENSIG(cen, off)); 126 if (CENSIG(cen, off) != CENSIG) { 127 print(" Wrong signature!"); 128 return; 129 } 130 print(" VerMadeby : %#6x [%d, %d.%d]%n", 131 CENVEM(cen, off), (CENVEM(cen, off) >> 8), 132 (CENVEM(cen, off) & 0xff) / 10, 133 (CENVEM(cen, off) & 0xff) % 10); 134 print(" VerExtract : %#6x [%d.%d]%n", 135 CENVER(cen, off), CENVER(cen, off) / 10, CENVER(cen, off) % 10); 136 print(" Flag : %#6x%n", CENFLG(cen, off)); 137 print(" Method : %#6x%n", CENHOW(cen, off)); 138 print(" LastMTime : %#10x [%tc]%n", 139 CENTIM(cen, off), dosToJavaTime(CENTIM(cen, off))); 140 print(" CRC : %#10x%n", CENCRC(cen, off)); 141 print(" CSize : %#10x%n", CENSIZ(cen, off)); 142 print(" Size : %#10x%n", CENLEN(cen, off)); 143 print(" NameLen : %#6x [%s]%n", 144 CENNAM(cen, off), new String(cen, off + CENHDR, CENNAM(cen, off))); 145 print(" ExtraLen : %#6x%n", CENEXT(cen, off)); 146 if (CENEXT(cen, off) != 0) 147 printExtra(cen, off + CENHDR + CENNAM(cen, off), CENEXT(cen, off)); 148 print(" CommentLen : %#6x%n", CENCOM(cen, off)); 149 print(" DiskStart : %#6x%n", CENDSK(cen, off)); 150 print(" Attrs : %#6x%n", CENATT(cen, off)); 151 print(" AttrsEx : %#10x%n", CENATX(cen, off)); 152 print(" LocOff : %#10x%n", CENOFF(cen, off)); 153 154 } 155 156 static long locoff(byte[] cen, int pos) { 157 long locoff = CENOFF(cen, pos); 158 if (locoff == ZIP64_MINVAL) { //ZIP64 159 int off = pos + CENHDR + CENNAM(cen, pos); 160 int end = off + CENEXT(cen, pos); 161 while (off + 4 < end) { 162 int tag = SH(cen, off); 163 int sz = SH(cen, off + 2); 164 if (tag != EXTID_ZIP64) { 165 off += 4 + sz; 166 continue; 167 } 168 off += 4; 169 if (CENLEN(cen, pos) == ZIP64_MINVAL) 170 off += 8; 171 if (CENSIZ(cen, pos) == ZIP64_MINVAL) 172 off += 8; 173 return LL(cen, off); 174 } 175 // should never be here 176 } 177 return locoff; 178 } 179 180 static void printExtra(byte[] extra, int off, int len) { 181 int end = off + len; 182 while (off + 4 <= end) { 183 int tag = SH(extra, off); 184 int sz = SH(extra, off + 2); 185 print(" [tag=0x%04x, sz=%d, data= ", tag, sz); 186 if (off + sz > end) { 187 print(" Error: Invalid extra data, beyond extra length"); 188 break; 189 } 190 off += 4; 191 for (int i = 0; i < sz; i++) 192 print("%02x ", extra[off + i]); 193 print("]%n"); 194 switch (tag) { 195 case EXTID_ZIP64 : 196 print(" ->ZIP64: "); 197 int pos = off; 198 while (pos + 8 <= off + sz) { 199 print(" *0x%x ", LL(extra, pos)); 200 pos += 8; 201 } 202 print("%n"); 203 break; 204 case EXTID_NTFS: 205 print(" ->PKWare NTFS%n"); 206 // 4 bytes reserved 207 if (SH(extra, off + 4) != 0x0001 || SH(extra, off + 6) != 24) 208 print(" Error: Invalid NTFS sub-tag or subsz"); 209 print(" mtime:%tc%n", 210 winToJavaTime(LL(extra, off + 8))); 211 print(" atime:%tc%n", 212 winToJavaTime(LL(extra, off + 16))); 213 print(" ctime:%tc%n", 214 winToJavaTime(LL(extra, off + 24))); 215 break; 216 case EXTID_EXTT: 217 print(" ->Info-ZIP Extended Timestamp: flag=%x%n",extra[off]); 218 pos = off + 1 ; 219 while (pos + 4 <= off + sz) { 220 print(" *%tc%n", 221 unixToJavaTime(LG(extra, pos))); 222 pos += 4; 223 } 224 break; 225 default: 226 print(" ->[tag=%x, size=%d]%n", tag, sz); 227 } 228 off += sz; 229 } 230 } 231 }