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          final 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          final 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          final 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 (final 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      @Test
97      public void testParseCentral() throws Exception {
98          final ZipExtraField[] ze = ExtraFieldUtils.parse(data,false);
99          assertEquals("number of fields", 2, ze.length);
100         assertTrue("type field 1", ze[0] instanceof AsiExtraField);
101         assertEquals("mode field 1", 040755,
102                      ((AsiExtraField) ze[0]).getMode());
103         assertTrue("type field 2", ze[1] instanceof UnrecognizedExtraField);
104         assertEquals("data length field 2", 1,
105                      ze[1].getCentralDirectoryLength().getValue());
106 
107     }
108 
109     @Test
110     public void testParseWithRead() throws Exception {
111         ZipExtraField[] ze =
112             ExtraFieldUtils.parse(data, 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 UnrecognizedExtraField);
119         assertEquals("data length field 2", 1,
120                      ze[1].getLocalFileDataLength().getValue());
121 
122         final byte[] data2 = new byte[data.length-1];
123         System.arraycopy(data, 0, data2, 0, data2.length);
124         ze = ExtraFieldUtils.parse(data2, true,
125                                    ExtraFieldUtils.UnparseableExtraField.READ);
126         assertEquals("number of fields", 2, ze.length);
127         assertTrue("type field 1", ze[0] instanceof AsiExtraField);
128         assertEquals("mode field 1", 040755,
129                      ((AsiExtraField) ze[0]).getMode());
130         assertTrue("type field 2", ze[1] instanceof UnparseableExtraFieldData);
131         assertEquals("data length field 2", 4,
132                      ze[1].getLocalFileDataLength().getValue());
133         for (int i = 0; i < 4; i++) {
134             assertEquals("byte number " + i,
135                          data2[data.length - 5 + i],
136                          ze[1].getLocalFileDataData()[i]);
137         }
138     }
139 
140     @Test
141     public void testParseWithSkip() throws Exception {
142         ZipExtraField[] ze =
143             ExtraFieldUtils.parse(data, true,
144                                   ExtraFieldUtils.UnparseableExtraField.SKIP);
145         assertEquals("number of fields", 2, ze.length);
146         assertTrue("type field 1", ze[0] instanceof AsiExtraField);
147         assertEquals("mode field 1", 040755,
148                      ((AsiExtraField) ze[0]).getMode());
149         assertTrue("type field 2", ze[1] instanceof UnrecognizedExtraField);
150         assertEquals("data length field 2", 1,
151                      ze[1].getLocalFileDataLength().getValue());
152 
153         final byte[] data2 = new byte[data.length-1];
154         System.arraycopy(data, 0, data2, 0, data2.length);
155         ze = ExtraFieldUtils.parse(data2, true,
156                                    ExtraFieldUtils.UnparseableExtraField.SKIP);
157         assertEquals("number of fields", 1, ze.length);
158         assertTrue("type field 1", ze[0] instanceof AsiExtraField);
159         assertEquals("mode field 1", 040755,
160                      ((AsiExtraField) ze[0]).getMode());
161     }
162 
163     /**
164      * Test merge methods
165      */
166     @Test
167     public void testMerge() {
168         final byte[] local =
169             ExtraFieldUtils.mergeLocalFileDataData(new ZipExtraField[] {a, dummy});
170         assertEquals("local length", data.length, local.length);
171         for (int i=0; i<local.length; i++) {
172             assertEquals("local byte "+i, data[i], local[i]);
173         }
174 
175         final byte[] dummyCentral = dummy.getCentralDirectoryData();
176         final byte[] data2 = new byte[4 + aLocal.length + 4 + dummyCentral.length];
177         System.arraycopy(data, 0, data2, 0, 4 + aLocal.length + 2);
178         System.arraycopy(dummy.getCentralDirectoryLength().getBytes(), 0,
179                          data2, 4+aLocal.length+2, 2);
180         System.arraycopy(dummyCentral, 0, data2,
181                          4+aLocal.length+4, dummyCentral.length);
182 
183 
184         final byte[] central =
185             ExtraFieldUtils.mergeCentralDirectoryData(new ZipExtraField[] {a, dummy});
186         assertEquals("central length", data2.length, central.length);
187         for (int i=0; i<central.length; i++) {
188             assertEquals("central byte "+i, data2[i], central[i]);
189         }
190 
191     }
192 
193     @Test
194     public void testMergeWithUnparseableData() throws Exception {
195         final ZipExtraField d = new UnparseableExtraFieldData();
196         final byte[] b = UNRECOGNIZED_HEADER.getBytes();
197         d.parseFromLocalFileData(new byte[] {b[0], b[1], 1, 0}, 0, 4);
198         final byte[] local =
199             ExtraFieldUtils.mergeLocalFileDataData(new ZipExtraField[] {a, d});
200         assertEquals("local length", data.length - 1, local.length);
201         for (int i = 0; i < local.length; i++) {
202             assertEquals("local byte " + i, data[i], local[i]);
203         }
204 
205         final byte[] dCentral = d.getCentralDirectoryData();
206         final byte[] data2 = new byte[4 + aLocal.length + dCentral.length];
207         System.arraycopy(data, 0, data2, 0, 4 + aLocal.length + 2);
208         System.arraycopy(dCentral, 0, data2,
209                          4 + aLocal.length, dCentral.length);
210 
211 
212         final byte[] central =
213             ExtraFieldUtils.mergeCentralDirectoryData(new ZipExtraField[] {a, d});
214         assertEquals("central length", data2.length, central.length);
215         for (int i = 0; i < central.length; i++) {
216             assertEquals("central byte " + i, data2[i], central[i]);
217         }
218 
219     }
220 }