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 } |
|