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