View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one or more
3    *  contributor license agreements.  See the NOTICE file distributed with
4    *  this work for additional information regarding copyright ownership.
5    *  The ASF licenses this file to You under the Apache License, Version 2.0
6    *  (the "License"); you may not use this file except in compliance with
7    *  the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   *
17   */
18  
19  package org.apache.commons.compress.archivers.zip;
20  
21  import static org.apache.commons.compress.AbstractTestCase.getFile;
22  import static org.junit.Assert.*;
23  
24  import java.io.File;
25  import java.io.FileInputStream;
26  import java.io.FileOutputStream;
27  import java.io.InputStream;
28  import java.io.OutputStream;
29  import java.util.ArrayList;
30  import java.util.Arrays;
31  import java.util.Collections;
32  import java.util.Enumeration;
33  import java.util.TreeMap;
34  import java.util.zip.ZipEntry;
35  
36  import org.apache.commons.compress.utils.IOUtils;
37  import org.junit.After;
38  import org.junit.Test;
39  
40  public class ZipFileTest {
41      private ZipFile zf = null;
42  
43      @After
44      public void tearDown() {
45          ZipFile.closeQuietly(zf);
46      }
47  
48      @Test
49      public void testCDOrder() throws Exception {
50          readOrderTest();
51          ArrayList<ZipArchiveEntry> l = Collections.list(zf.getEntries());
52          assertEntryName(l, 0, "AbstractUnicodeExtraField");
53          assertEntryName(l, 1, "AsiExtraField");
54          assertEntryName(l, 2, "ExtraFieldUtils");
55          assertEntryName(l, 3, "FallbackZipEncoding");
56          assertEntryName(l, 4, "GeneralPurposeBit");
57          assertEntryName(l, 5, "JarMarker");
58          assertEntryName(l, 6, "NioZipEncoding");
59          assertEntryName(l, 7, "Simple8BitZipEncoding");
60          assertEntryName(l, 8, "UnicodeCommentExtraField");
61          assertEntryName(l, 9, "UnicodePathExtraField");
62          assertEntryName(l, 10, "UnixStat");
63          assertEntryName(l, 11, "UnparseableExtraFieldData");
64          assertEntryName(l, 12, "UnrecognizedExtraField");
65          assertEntryName(l, 13, "ZipArchiveEntry");
66          assertEntryName(l, 14, "ZipArchiveInputStream");
67          assertEntryName(l, 15, "ZipArchiveOutputStream");
68          assertEntryName(l, 16, "ZipEncoding");
69          assertEntryName(l, 17, "ZipEncodingHelper");
70          assertEntryName(l, 18, "ZipExtraField");
71          assertEntryName(l, 19, "ZipUtil");
72          assertEntryName(l, 20, "ZipLong");
73          assertEntryName(l, 21, "ZipShort");
74          assertEntryName(l, 22, "ZipFile");
75      }
76  
77      @Test
78      public void testPhysicalOrder() throws Exception {
79          readOrderTest();
80          ArrayList<ZipArchiveEntry> l = Collections.list(zf.getEntriesInPhysicalOrder());
81          assertEntryName(l, 0, "AbstractUnicodeExtraField");
82          assertEntryName(l, 1, "AsiExtraField");
83          assertEntryName(l, 2, "ExtraFieldUtils");
84          assertEntryName(l, 3, "FallbackZipEncoding");
85          assertEntryName(l, 4, "GeneralPurposeBit");
86          assertEntryName(l, 5, "JarMarker");
87          assertEntryName(l, 6, "NioZipEncoding");
88          assertEntryName(l, 7, "Simple8BitZipEncoding");
89          assertEntryName(l, 8, "UnicodeCommentExtraField");
90          assertEntryName(l, 9, "UnicodePathExtraField");
91          assertEntryName(l, 10, "UnixStat");
92          assertEntryName(l, 11, "UnparseableExtraFieldData");
93          assertEntryName(l, 12, "UnrecognizedExtraField");
94          assertEntryName(l, 13, "ZipArchiveEntry");
95          assertEntryName(l, 14, "ZipArchiveInputStream");
96          assertEntryName(l, 15, "ZipArchiveOutputStream");
97          assertEntryName(l, 16, "ZipEncoding");
98          assertEntryName(l, 17, "ZipEncodingHelper");
99          assertEntryName(l, 18, "ZipExtraField");
100         assertEntryName(l, 19, "ZipFile");
101         assertEntryName(l, 20, "ZipLong");
102         assertEntryName(l, 21, "ZipShort");
103         assertEntryName(l, 22, "ZipUtil");
104     }
105 
106     @Test
107     public void testDoubleClose() throws Exception {
108         readOrderTest();
109         zf.close();
110         try {
111             zf.close();
112         } catch (Exception ex) {
113             fail("Caught exception of second close");
114         }
115     }
116 
117     @Test
118     public void testReadingOfStoredEntry() throws Exception {
119         File f = File.createTempFile("commons-compress-zipfiletest", ".zip");
120         f.deleteOnExit();
121         OutputStream o = null;
122         InputStream i = null;
123         try {
124             o = new FileOutputStream(f);
125             ZipArchiveOutputStream zo = new ZipArchiveOutputStream(o);
126             ZipArchiveEntry ze = new ZipArchiveEntry("foo");
127             ze.setMethod(ZipEntry.STORED);
128             ze.setSize(4);
129             ze.setCrc(0xb63cfbcdl);
130             zo.putArchiveEntry(ze);
131             zo.write(new byte[] { 1, 2, 3, 4 });
132             zo.closeArchiveEntry();
133             zo.close();
134             o.close();
135             o  = null;
136 
137             zf = new ZipFile(f);
138             ze = zf.getEntry("foo");
139             assertNotNull(ze);
140             i = zf.getInputStream(ze);
141             byte[] b = new byte[4];
142             assertEquals(4, i.read(b));
143             assertEquals(-1, i.read());
144         } finally {
145             if (o != null) {
146                 o.close();
147             }
148             if (i != null) {
149                 i.close();
150             }
151             f.delete();
152         }
153     }
154 
155     /**
156      * @see "https://issues.apache.org/jira/browse/COMPRESS-176"
157      */
158     @Test
159     public void testWinzipBackSlashWorkaround() throws Exception {
160         File archive = getFile("test-winzip.zip");
161         zf = new ZipFile(archive);
162         assertNull(zf.getEntry("\u00e4\\\u00fc.txt"));
163         assertNotNull(zf.getEntry("\u00e4/\u00fc.txt"));
164     }
165 
166     /**
167      * Test case for 
168      * <a href="https://issues.apache.org/jira/browse/COMPRESS-208"
169      * >COMPRESS-208</a>.
170      */
171     @Test
172     public void testSkipsPK00Prefix() throws Exception {
173         File archive = getFile("COMPRESS-208.zip");
174         zf = new ZipFile(archive);
175         assertNotNull(zf.getEntry("test1.xml"));
176         assertNotNull(zf.getEntry("test2.xml"));
177     }
178 
179     @Test
180     public void testUnixSymlinkSampleFile() throws Exception {
181         final String entryPrefix = "COMPRESS-214_unix_symlinks/";
182         final TreeMap<String, String> expectedVals = new TreeMap<String, String>();
183 
184         // I threw in some Japanese characters to keep things interesting.
185         expectedVals.put(entryPrefix + "link1", "../COMPRESS-214_unix_symlinks/./a/b/c/../../../\uF999");
186         expectedVals.put(entryPrefix + "link2", "../COMPRESS-214_unix_symlinks/./a/b/c/../../../g");
187         expectedVals.put(entryPrefix + "link3", "../COMPRESS-214_unix_symlinks/././a/b/c/../../../\u76F4\u6A39");
188         expectedVals.put(entryPrefix + "link4", "\u82B1\u5B50/\u745B\u5B50");
189         expectedVals.put(entryPrefix + "\uF999", "./\u82B1\u5B50/\u745B\u5B50/\u5897\u8C37/\uF999");
190         expectedVals.put(entryPrefix + "g", "./a/b/c/d/e/f/g");
191         expectedVals.put(entryPrefix + "\u76F4\u6A39", "./g");
192 
193         // Notice how a directory link might contain a trailing slash, or it might not.
194         // Also note:  symlinks are always stored as files, even if they link to directories.
195         expectedVals.put(entryPrefix + "link5", "../COMPRESS-214_unix_symlinks/././a/b");
196         expectedVals.put(entryPrefix + "link6", "../COMPRESS-214_unix_symlinks/././a/b/");
197 
198         // I looked into creating a test with hard links, but zip does not appear to
199         // support hard links, so nevermind.
200 
201         File archive = getFile("COMPRESS-214_unix_symlinks.zip");
202 
203         zf = new ZipFile(archive);
204         Enumeration<ZipArchiveEntry> en = zf.getEntries();
205         while (en.hasMoreElements()) {
206             ZipArchiveEntry zae = en.nextElement();
207             String link = zf.getUnixSymlink(zae);
208             if (zae.isUnixSymlink()) {
209                 String name = zae.getName();
210                 String expected = expectedVals.get(name);
211                 assertEquals(expected, link);
212             } else {
213                 // Should be null if it's not a symlink!
214                 assertNull(link);
215             }
216         }
217     }
218 
219     /**
220      * @see "https://issues.apache.org/jira/browse/COMPRESS-227"
221      */
222     @Test
223     public void testDuplicateEntry() throws Exception {
224         File archive = getFile("COMPRESS-227.zip");
225         zf = new ZipFile(archive);
226 
227         ZipArchiveEntry ze = zf.getEntry("test1.txt");
228         assertNotNull(ze);
229         assertNotNull(zf.getInputStream(ze));
230 
231         int numberOfEntries = 0;
232         for (ZipArchiveEntry entry : zf.getEntries("test1.txt")) {
233             numberOfEntries++;
234             assertNotNull(zf.getInputStream(entry));
235         }
236         assertEquals(2, numberOfEntries);
237     }
238 
239     /**
240      * @see "https://issues.apache.org/jira/browse/COMPRESS-228"
241      */
242     @Test
243     public void testExcessDataInZip64ExtraField() throws Exception {
244         File archive = getFile("COMPRESS-228.zip");
245         zf = new ZipFile(archive);
246         // actually, if we get here, the test already has passed
247 
248         ZipArchiveEntry ze = zf.getEntry("src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java");
249         assertEquals(26101, ze.getSize());
250     }
251 
252     @Test
253     public void testUnshrinking() throws Exception {
254         zf = new ZipFile(getFile("SHRUNK.ZIP"));
255         ZipArchiveEntry test = zf.getEntry("TEST1.XML");
256         FileInputStream original = new FileInputStream(getFile("test1.xml"));
257         try {
258             assertArrayEquals(IOUtils.toByteArray(original),
259                               IOUtils.toByteArray(zf.getInputStream(test)));
260         } finally {
261             original.close();
262         }
263         test = zf.getEntry("TEST2.XML");
264         original = new FileInputStream(getFile("test2.xml"));
265         try {
266             assertArrayEquals(IOUtils.toByteArray(original),
267                               IOUtils.toByteArray(zf.getInputStream(test)));
268         } finally {
269             original.close();
270         }
271     }
272 
273     /**
274      * Test case for 
275      * <a href="https://issues.apache.org/jira/browse/COMPRESS-264"
276      * >COMPRESS-264</a>.
277      */
278     @Test
279     public void testReadingOfFirstStoredEntry() throws Exception {
280         File archive = getFile("COMPRESS-264.zip");
281         zf = new ZipFile(archive);
282         ZipArchiveEntry ze = zf.getEntry("test.txt");
283         assertEquals(5, ze.getSize());
284         assertArrayEquals(new byte[] {'d', 'a', 't', 'a', '\n'},
285                           IOUtils.toByteArray(zf.getInputStream(ze)));
286     }
287 
288     @Test
289     public void testUnzipBZip2CompressedEntry() throws Exception {
290         File archive = getFile("bzip2-zip.zip");
291         zf = new ZipFile(archive);
292         ZipArchiveEntry ze = zf.getEntry("lots-of-as");
293         assertEquals(42, ze.getSize());
294         byte[] expected = new byte[42];
295         Arrays.fill(expected , (byte)'a');
296         assertArrayEquals(expected, IOUtils.toByteArray(zf.getInputStream(ze)));
297     }
298 
299     /*
300      * ordertest.zip has been handcrafted.
301      *
302      * It contains enough files so any random coincidence of
303      * entries.keySet() and central directory order would be unlikely
304      * - in fact testCDOrder fails in svn revision 920284.
305      *
306      * The central directory has ZipFile and ZipUtil swapped so
307      * central directory order is different from entry data order.
308      */
309     private void readOrderTest() throws Exception {
310         File archive = getFile("ordertest.zip");
311         zf = new ZipFile(archive);
312     }
313 
314     private static void assertEntryName(ArrayList<ZipArchiveEntry> entries,
315                                         int index,
316                                         String expectedName) {
317         ZipArchiveEntry ze = entries.get(index);
318         assertEquals("src/main/java/org/apache/commons/compress/archivers/zip/"
319                      + expectedName + ".java",
320                      ze.getName());
321     }
322 }