1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 package org.apache.commons.compress.archivers.zip; 20 21 import org.junit.Before; 22 import org.junit.Test; 23 24 import java.io.File; 25 import java.util.Arrays; 26 import java.util.Enumeration; 27 import java.util.zip.ZipException; 28 29 import static org.apache.commons.compress.AbstractTestCase.getFile; 30 import static org.junit.Assert.assertArrayEquals; 31 import static org.junit.Assert.assertEquals; 32 import static org.junit.Assert.assertFalse; 33 import static org.junit.Assert.assertTrue; 34 35 public class X7875_NewUnixTest { 36 37 private final static ZipShort X7875 = new ZipShort(0x7875); 38 39 private X7875_NewUnix xf; 40 41 @Before before()42 public void before() { 43 xf = new X7875_NewUnix(); 44 } 45 46 47 @Test testSampleFile()48 public void testSampleFile() throws Exception { 49 final File archive = getFile("COMPRESS-211_uid_gid_zip_test.zip"); 50 ZipFile zf = null; 51 52 try { 53 zf = new ZipFile(archive); 54 final Enumeration<ZipArchiveEntry> en = zf.getEntries(); 55 56 // We expect EVERY entry of this zip file (dir & file) to 57 // contain extra field 0x7875. 58 while (en.hasMoreElements()) { 59 60 final ZipArchiveEntry zae = en.nextElement(); 61 final String name = zae.getName(); 62 final X7875_NewUnix xf = (X7875_NewUnix) zae.getExtraField(X7875); 63 64 // The directory entry in the test zip file is uid/gid 1000. 65 long expected = 1000; 66 if (name.contains("uid555_gid555")) { 67 expected = 555; 68 } else if (name.contains("uid5555_gid5555")) { 69 expected = 5555; 70 } else if (name.contains("uid55555_gid55555")) { 71 expected = 55555; 72 } else if (name.contains("uid555555_gid555555")) { 73 expected = 555555; 74 } else if (name.contains("min_unix")) { 75 expected = 0; 76 } else if (name.contains("max_unix")) { 77 // 2^32-2 was the biggest UID/GID I could create on my linux! 78 // (December 2012, linux kernel 3.4) 79 expected = 0x100000000L - 2; 80 } 81 assertEquals(expected, xf.getUID()); 82 assertEquals(expected, xf.getGID()); 83 } 84 } finally { 85 if (zf != null) { 86 zf.close(); 87 } 88 } 89 } 90 91 @Test testGetHeaderId()92 public void testGetHeaderId() { 93 assertEquals(X7875, xf.getHeaderId()); 94 } 95 96 @Test testMisc()97 public void testMisc() throws Exception { 98 assertFalse(xf.equals(new Object())); 99 assertTrue(xf.toString().startsWith("0x7875 Zip Extra Field")); 100 final Object o = xf.clone(); 101 assertEquals(o.hashCode(), xf.hashCode()); 102 assertTrue(xf.equals(o)); 103 xf.setUID(12345); 104 assertFalse(xf.equals(o)); 105 } 106 107 @Test testTrimLeadingZeroesForceMinLength4()108 public void testTrimLeadingZeroesForceMinLength4() { 109 final byte[] NULL = null; 110 final byte[] EMPTY = new byte[0]; 111 final byte[] ONE_ZERO = {0}; 112 final byte[] TWO_ZEROES = {0, 0}; 113 final byte[] FOUR_ZEROES = {0, 0, 0, 0}; 114 final byte[] SEQUENCE = {1, 2, 3}; 115 final byte[] SEQUENCE_LEADING_ZERO = {0, 1, 2, 3}; 116 final byte[] SEQUENCE_LEADING_ZEROES = {0, 0, 0, 0, 0, 0, 0, 1, 2, 3}; 117 final byte[] TRAILING_ZERO = {1, 2, 3, 0}; 118 final byte[] PADDING_ZERO = {0, 1, 2, 3, 0}; 119 final byte[] SEQUENCE6 = {1, 2, 3, 4, 5, 6}; 120 final byte[] SEQUENCE6_LEADING_ZERO = {0, 1, 2, 3, 4, 5, 6}; 121 122 assertTrue(NULL == trimTest(NULL)); 123 assertTrue(Arrays.equals(ONE_ZERO, trimTest(EMPTY))); 124 assertTrue(Arrays.equals(ONE_ZERO, trimTest(ONE_ZERO))); 125 assertTrue(Arrays.equals(ONE_ZERO, trimTest(TWO_ZEROES))); 126 assertTrue(Arrays.equals(ONE_ZERO, trimTest(FOUR_ZEROES))); 127 assertTrue(Arrays.equals(SEQUENCE, trimTest(SEQUENCE))); 128 assertTrue(Arrays.equals(SEQUENCE, trimTest(SEQUENCE_LEADING_ZERO))); 129 assertTrue(Arrays.equals(SEQUENCE, trimTest(SEQUENCE_LEADING_ZEROES))); 130 assertTrue(Arrays.equals(TRAILING_ZERO, trimTest(TRAILING_ZERO))); 131 assertTrue(Arrays.equals(TRAILING_ZERO, trimTest(PADDING_ZERO))); 132 assertTrue(Arrays.equals(SEQUENCE6, trimTest(SEQUENCE6))); 133 assertTrue(Arrays.equals(SEQUENCE6, trimTest(SEQUENCE6_LEADING_ZERO))); 134 } 135 trimTest(final byte[] b)136 private static byte[] trimTest(final byte[] b) { return X7875_NewUnix.trimLeadingZeroesForceMinLength(b); } 137 138 @Test testParseReparse()139 public void testParseReparse() throws ZipException { 140 141 // Version=1, Len=0, Len=0. 142 final byte[] ZERO_LEN = {1, 0, 0}; 143 144 // Version=1, Len=1, zero, Len=1, zero. 145 final byte[] ZERO_UID_GID = {1, 1, 0, 1, 0}; 146 147 // Version=1, Len=1, one, Len=1, one 148 final byte[] ONE_UID_GID = {1, 1, 1, 1, 1}; 149 150 // Version=1, Len=2, one thousand, Len=2, one thousand 151 final byte[] ONE_THOUSAND_UID_GID = {1, 2, -24, 3, 2, -24, 3}; 152 153 // (2^32 - 2). I guess they avoid (2^32 - 1) since it's identical to -1 in 154 // two's complement, and -1 often has a special meaning. 155 final byte[] UNIX_MAX_UID_GID = {1, 4, -2, -1, -1, -1, 4, -2, -1, -1, -1}; 156 157 // Version=1, Len=5, 2^32, Len=5, 2^32 + 1 158 // Esoteric test: can we handle 40 bit numbers? 159 final byte[] LENGTH_5 = {1, 5, 0, 0, 0, 0, 1, 5, 1, 0, 0, 0, 1}; 160 161 // Version=1, Len=8, 2^63 - 2, Len=8, 2^63 - 1 162 // Esoteric test: can we handle 64 bit numbers? 163 final byte[] LENGTH_8 = {1, 8, -2, -1, -1, -1, -1, -1, -1, 127, 8, -1, -1, -1, -1, -1, -1, -1, 127}; 164 165 final long TWO_TO_32 = 0x100000000L; 166 final long MAX = TWO_TO_32 - 2; 167 168 parseReparse(0, 0, ZERO_LEN, 0, 0); 169 parseReparse(0, 0, ZERO_UID_GID, 0, 0); 170 parseReparse(1, 1, ONE_UID_GID, 1, 1); 171 parseReparse(1000, 1000, ONE_THOUSAND_UID_GID, 1000, 1000); 172 parseReparse(MAX, MAX, UNIX_MAX_UID_GID, MAX, MAX); 173 parseReparse(-2, -2, UNIX_MAX_UID_GID, MAX, MAX); 174 parseReparse(TWO_TO_32, TWO_TO_32 + 1, LENGTH_5, TWO_TO_32, TWO_TO_32 + 1); 175 parseReparse(Long.MAX_VALUE - 1, Long.MAX_VALUE, LENGTH_8, Long.MAX_VALUE - 1, Long.MAX_VALUE); 176 177 // We never emit this, but we should be able to parse it: 178 final byte[] SPURIOUS_ZEROES_1 = {1, 4, -1, 0, 0, 0, 4, -128, 0, 0, 0}; 179 final byte[] EXPECTED_1 = {1, 1, -1, 1, -128}; 180 xf.parseFromLocalFileData(SPURIOUS_ZEROES_1, 0, SPURIOUS_ZEROES_1.length); 181 182 assertEquals(255, xf.getUID()); 183 assertEquals(128, xf.getGID()); 184 assertTrue(Arrays.equals(EXPECTED_1, xf.getLocalFileDataData())); 185 186 final byte[] SPURIOUS_ZEROES_2 = {1, 4, -1, -1, 0, 0, 4, 1, 2, 0, 0}; 187 final byte[] EXPECTED_2 = {1, 2, -1, -1, 2, 1, 2}; 188 xf.parseFromLocalFileData(SPURIOUS_ZEROES_2, 0, SPURIOUS_ZEROES_2.length); 189 190 assertEquals(65535, xf.getUID()); 191 assertEquals(513, xf.getGID()); 192 assertTrue(Arrays.equals(EXPECTED_2, xf.getLocalFileDataData())); 193 } 194 195 parseReparse( final long uid, final long gid, final byte[] expected, final long expectedUID, final long expectedGID )196 private void parseReparse( 197 final long uid, 198 final long gid, 199 final byte[] expected, 200 final long expectedUID, 201 final long expectedGID 202 ) throws ZipException { 203 204 // Initial local parse (init with garbage to avoid defaults causing test to pass). 205 xf.setUID(54321); 206 xf.setGID(12345); 207 xf.parseFromLocalFileData(expected, 0, expected.length); 208 assertEquals(expectedUID, xf.getUID()); 209 assertEquals(expectedGID, xf.getGID()); 210 211 xf.setUID(uid); 212 xf.setGID(gid); 213 if (expected.length < 5) { 214 // We never emit zero-length entries. 215 assertEquals(5, xf.getLocalFileDataLength().getValue()); 216 } else { 217 assertEquals(expected.length, xf.getLocalFileDataLength().getValue()); 218 } 219 byte[] result = xf.getLocalFileDataData(); 220 if (expected.length < 5) { 221 // We never emit zero-length entries. 222 assertTrue(Arrays.equals(new byte[]{1,1,0,1,0}, result)); 223 } else { 224 assertTrue(Arrays.equals(expected, result)); 225 } 226 227 228 229 // And now we re-parse: 230 xf.parseFromLocalFileData(result, 0, result.length); 231 232 // Did uid/gid change from re-parse? They shouldn't! 233 assertEquals(expectedUID, xf.getUID()); 234 assertEquals(expectedGID, xf.getGID()); 235 236 assertEquals(0, xf.getCentralDirectoryLength().getValue()); 237 result = xf.getCentralDirectoryData(); 238 assertArrayEquals(new byte[0], result); 239 240 // And now we re-parse: 241 xf.parseFromCentralDirectoryData(result, 0, result.length); 242 243 // Did uid/gid change from 2nd re-parse? They shouldn't! 244 assertEquals(expectedUID, xf.getUID()); 245 assertEquals(expectedGID, xf.getGID()); 246 } 247 } 248