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.junit.Assert.*;
22  
23  import org.junit.Before;
24  import org.junit.Test;
25  
26  /**
27   * JUnit testcases for org.apache.commons.compress.archivers.zip.ExtraFieldUtils.
28   *
29   */
30  public class ExtraFieldUtilsTest implements UnixStat {
31  
32      /**
33       * Header-ID of a ZipExtraField not supported by Commons Compress.
34       *
35       * <p>Used to be ZipShort(1) but this is the ID of the Zip64 extra
36       * field.</p>
37       */
38      static final ZipShort UNRECOGNIZED_HEADER = new ZipShort(0x5555);
39  
40      private AsiExtraField a;
41      private UnrecognizedExtraField dummy;
42      private byte[] data;
43      private byte[] aLocal;
44  
45      @Before
46      public void setUp() {
47          a = new AsiExtraField();
48          a.setMode(0755);
49          a.setDirectory(true);
50          dummy = new UnrecognizedExtraField();
51          dummy.setHeaderId(UNRECOGNIZED_HEADER);
52          dummy.setLocalFileDataData(new byte[] {0});
53          dummy.setCentralDirectoryData(new byte[] {0});
54  
55          aLocal = a.getLocalFileDataData();
56          byte[] dummyLocal = dummy.getLocalFileDataData();
57          data = new byte[4 + aLocal.length + 4 + dummyLocal.length];
58          System.arraycopy(a.getHeaderId().getBytes(), 0, data, 0, 2);
59          System.arraycopy(a.getLocalFileDataLength().getBytes(), 0, data, 2, 2);
60          System.arraycopy(aLocal, 0, data, 4, aLocal.length);
61          System.arraycopy(dummy.getHeaderId().getBytes(), 0, data,
62                           4+aLocal.length, 2);
63          System.arraycopy(dummy.getLocalFileDataLength().getBytes(), 0, data,
64                           4+aLocal.length+2, 2);
65          System.arraycopy(dummyLocal, 0, data,
66                           4+aLocal.length+4, dummyLocal.length);
67  
68      }
69  
70      /**
71       * test parser.
72       */
73      @Test
74      public void testParse() throws Exception {
75          ZipExtraField[] ze = ExtraFieldUtils.parse(data);
76          assertEquals("number of fields", 2, ze.length);
77          assertTrue("type field 1", ze[0] instanceof AsiExtraField);
78          assertEquals("mode field 1", 040755,
79                       ((AsiExtraField) ze[0]).getMode());
80          assertTrue("type field 2", ze[1] instanceof UnrecognizedExtraField);
81          assertEquals("data length field 2", 1,
82                       ze[1].getLocalFileDataLength().getValue());
83  
84          byte[] data2 = new byte[data.length-1];
85          System.arraycopy(data, 0, data2, 0, data2.length);
86          try {
87              ExtraFieldUtils.parse(data2);
88              fail("data should be invalid");
89          } catch (Exception e) {
90              assertEquals("message",
91                           "bad extra field starting at "+(4 + aLocal.length)
92                           + ".  Block length of 1 bytes exceeds remaining data of 0 bytes.",
93                           e.getMessage());
94          }
95      }
96  
97      @Test
98      public void testParseWithRead() throws Exception {
99          ZipExtraField[] ze =
100             ExtraFieldUtils.parse(data, true,
101                                   ExtraFieldUtils.UnparseableExtraField.READ);
102         assertEquals("number of fields", 2, ze.length);
103         assertTrue("type field 1", ze[0] instanceof AsiExtraField);
104         assertEquals("mode field 1", 040755,
105                      ((AsiExtraField) ze[0]).getMode());
106         assertTrue("type field 2", ze[1] instanceof UnrecognizedExtraField);
107         assertEquals("data length field 2", 1,
108                      ze[1].getLocalFileDataLength().getValue());
109 
110         byte[] data2 = new byte[data.length-1];
111         System.arraycopy(data, 0, data2, 0, data2.length);
112         ze = ExtraFieldUtils.parse(data2, true,
113                                    ExtraFieldUtils.UnparseableExtraField.READ);
114         assertEquals("number of fields", 2, ze.length);
115         assertTrue("type field 1", ze[0] instanceof AsiExtraField);
116         assertEquals("mode field 1", 040755,
117                      ((AsiExtraField) ze[0]).getMode());
118         assertTrue("type field 2", ze[1] instanceof UnparseableExtraFieldData);
119         assertEquals("data length field 2", 4,
120                      ze[1].getLocalFileDataLength().getValue());
121         for (int i = 0; i < 4; i++) {
122             assertEquals("byte number " + i,
123                          data2[data.length - 5 + i],
124                          ze[1].getLocalFileDataData()[i]);
125         }
126     }
127 
128     @Test
129     public void testParseWithSkip() throws Exception {
130         ZipExtraField[] ze =
131             ExtraFieldUtils.parse(data, true,
132                                   ExtraFieldUtils.UnparseableExtraField.SKIP);
133         assertEquals("number of fields", 2, ze.length);
134         assertTrue("type field 1", ze[0] instanceof AsiExtraField);
135         assertEquals("mode field 1", 040755,
136                      ((AsiExtraField) ze[0]).getMode());
137         assertTrue("type field 2", ze[1] instanceof UnrecognizedExtraField);
138         assertEquals("data length field 2", 1,
139                      ze[1].getLocalFileDataLength().getValue());
140 
141         byte[] data2 = new byte[data.length-1];
142         System.arraycopy(data, 0, data2, 0, data2.length);
143         ze = ExtraFieldUtils.parse(data2, true,
144                                    ExtraFieldUtils.UnparseableExtraField.SKIP);
145         assertEquals("number of fields", 1, ze.length);
146         assertTrue("type field 1", ze[0] instanceof AsiExtraField);
147         assertEquals("mode field 1", 040755,
148                      ((AsiExtraField) ze[0]).getMode());
149     }
150 
151     /**
152      * Test merge methods
153      */
154     @Test
155     public void testMerge() {
156         byte[] local =
157             ExtraFieldUtils.mergeLocalFileDataData(new ZipExtraField[] {a, dummy});
158         assertEquals("local length", data.length, local.length);
159         for (int i=0; i<local.length; i++) {
160             assertEquals("local byte "+i, data[i], local[i]);
161         }
162 
163         byte[] dummyCentral = dummy.getCentralDirectoryData();
164         byte[] data2 = new byte[4 + aLocal.length + 4 + dummyCentral.length];
165         System.arraycopy(data, 0, data2, 0, 4 + aLocal.length + 2);
166         System.arraycopy(dummy.getCentralDirectoryLength().getBytes(), 0,
167                          data2, 4+aLocal.length+2, 2);
168         System.arraycopy(dummyCentral, 0, data2,
169                          4+aLocal.length+4, dummyCentral.length);
170 
171 
172         byte[] central =
173             ExtraFieldUtils.mergeCentralDirectoryData(new ZipExtraField[] {a, dummy});
174         assertEquals("central length", data2.length, central.length);
175         for (int i=0; i<central.length; i++) {
176             assertEquals("central byte "+i, data2[i], central[i]);
177         }
178 
179     }
180 
181     @Test
182     public void testMergeWithUnparseableData() throws Exception {
183         ZipExtraField d = new UnparseableExtraFieldData();
184         byte[] b = UNRECOGNIZED_HEADER.getBytes();
185         d.parseFromLocalFileData(new byte[] {b[0], b[1], 1, 0}, 0, 4);
186         byte[] local =
187             ExtraFieldUtils.mergeLocalFileDataData(new ZipExtraField[] {a, d});
188         assertEquals("local length", data.length - 1, local.length);
189         for (int i = 0; i < local.length; i++) {
190             assertEquals("local byte " + i, data[i], local[i]);
191         }
192 
193         byte[] dCentral = d.getCentralDirectoryData();
194         byte[] data2 = new byte[4 + aLocal.length + dCentral.length];
195         System.arraycopy(data, 0, data2, 0, 4 + aLocal.length + 2);
196         System.arraycopy(dCentral, 0, data2,
197                          4 + aLocal.length, dCentral.length);
198 
199 
200         byte[] central =
201             ExtraFieldUtils.mergeCentralDirectoryData(new ZipExtraField[] {a, d});
202         assertEquals("central length", data2.length, central.length);
203         for (int i = 0; i < central.length; i++) {
204             assertEquals("central byte " + i, data2[i], central[i]);
205         }
206 
207     }
208 }