|
26 | 26 | */ |
27 | 27 | public class JvmZipReader extends AbstractZipReader { |
28 | 28 | private static final Logger logger = LoggerFactory.getLogger(JvmZipReader.class); |
| 29 | + private final boolean skipRevisitedCenToLocalLinks; |
29 | 30 |
|
30 | 31 | /** |
31 | 32 | * New reader with jvm allocator. |
32 | 33 | */ |
33 | 34 | public JvmZipReader() { |
34 | | - this(new JvmZipPartAllocator()); |
| 35 | + this(new JvmZipPartAllocator(), true); |
| 36 | + } |
| 37 | + |
| 38 | + /** |
| 39 | + * New reader with jvm allocator. |
| 40 | + * |
| 41 | + * @param skipRevisitedCenToLocalLinks |
| 42 | + * Flag to skip creating duplicate {@link LocalFileHeader} entries if multiple |
| 43 | + * {@link CentralDirectoryFileHeader} point to the same location. |
| 44 | + */ |
| 45 | + public JvmZipReader(boolean skipRevisitedCenToLocalLinks) { |
| 46 | + this(new JvmZipPartAllocator(), skipRevisitedCenToLocalLinks); |
35 | 47 | } |
36 | 48 |
|
37 | 49 | /** |
38 | 50 | * New reader with given allocator. |
39 | 51 | * |
40 | 52 | * @param allocator |
41 | 53 | * Allocator to use. |
| 54 | + * @param skipRevisitedCenToLocalLinks |
| 55 | + * Flag to skip creating duplicate {@link LocalFileHeader} entries if multiple |
| 56 | + * {@link CentralDirectoryFileHeader} point to the same location. |
42 | 57 | */ |
43 | | - public JvmZipReader(@Nonnull ZipPartAllocator allocator) { |
| 58 | + public JvmZipReader(@Nonnull ZipPartAllocator allocator, boolean skipRevisitedCenToLocalLinks) { |
44 | 59 | super(allocator); |
| 60 | + this.skipRevisitedCenToLocalLinks = skipRevisitedCenToLocalLinks; |
45 | 61 | } |
46 | 62 |
|
47 | 63 | @Override |
@@ -159,24 +175,31 @@ else if (data.getInt(jvmBaseFileOffset) == ZipPatterns.CENTRAL_DIRECTORY_FILE_HE |
159 | 175 | for (CentralDirectoryFileHeader directory : zip.getCentralDirectories()) { |
160 | 176 | long relative = directory.getRelativeOffsetOfLocalHeader(); |
161 | 177 | long offset = jvmBaseFileOffset + relative; |
162 | | - if (!offsets.contains(offset) && data.getInt(offset) == ZipPatterns.LOCAL_FILE_HEADER_QUAD) { |
163 | | - try { |
164 | | - LocalFileHeader file = newLocalFileHeader(); |
165 | | - if (file instanceof JvmLocalFileHeader) { |
166 | | - ((JvmLocalFileHeader) file).setOffsets(entryOffsets); |
167 | | - } |
168 | | - file.read(data, offset); |
169 | | - directory.link(file); |
170 | | - file.link(directory); |
171 | | - file.adoptLinkedCentralDirectoryValues(); |
172 | | - zip.addPart(file); |
173 | | - postProcessLocalFileHeader(file); |
174 | | - offsets.add(offset); |
175 | | - } catch (Exception ex) { |
176 | | - logger.warn("Failed to read 'local file header' at offset[{}]", offset, ex); |
177 | | - } |
178 | | - } else { |
| 178 | + boolean isNewOffset = offsets.add(offset); |
| 179 | + if (!isNewOffset) { |
| 180 | + logger.warn("Central-Directory-File-Header's offset[{}] was already visited", offset); |
| 181 | + if (skipRevisitedCenToLocalLinks) |
| 182 | + continue; |
| 183 | + } |
| 184 | + |
| 185 | + if (data.getInt(offset) != ZipPatterns.LOCAL_FILE_HEADER_QUAD) { |
179 | 186 | logger.warn("Central-Directory-File-Header's offset[{}] to Local-File-Header does not match the Local-File-Header magic!", offset); |
| 187 | + continue; |
| 188 | + } |
| 189 | + |
| 190 | + try { |
| 191 | + LocalFileHeader file = newLocalFileHeader(); |
| 192 | + if (file instanceof JvmLocalFileHeader) { |
| 193 | + ((JvmLocalFileHeader) file).setOffsets(entryOffsets); |
| 194 | + } |
| 195 | + file.read(data, offset); |
| 196 | + directory.link(file); |
| 197 | + file.link(directory); |
| 198 | + file.adoptLinkedCentralDirectoryValues(); |
| 199 | + zip.addPart(file); |
| 200 | + postProcessLocalFileHeader(file); |
| 201 | + } catch (Exception ex) { |
| 202 | + logger.warn("Failed to read 'local file header' at offset[{}]", offset, ex); |
180 | 203 | } |
181 | 204 | } |
182 | 205 |
|
|
0 commit comments