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