77
88import java .io .IOException ;
99
10- import static software .coley .llzip .ZipCompressions .* ;
10+ import static software .coley .llzip .ZipCompressions .STORED ;
1111
1212/**
1313 * ZIP LocalFileHeader structure.
@@ -35,8 +35,11 @@ public class LocalFileHeader implements ZipPart, ZipRead {
3535
3636 private transient String fileNameCache ;
3737
38+ private ByteData data ;
39+
3840 @ Override
3941 public void read (ByteData data , long offset ) {
42+ this .data = data ;
4043 this .offset = offset ;
4144 versionNeededToExtract = ByteDataUtil .readWord (data , offset + 4 );
4245 generalPurposeBitFlag = ByteDataUtil .readWord (data , offset + 6 );
@@ -59,6 +62,43 @@ public void read(ByteData data, long offset) {
5962 fileData = data .sliceOf (offset + 30 + fileNameLength + extraFieldLength , fileDataLength );
6063 }
6164
65+ /**
66+ * When called before being {@link #freeze() frozen} values can be adopted from the linked
67+ * {@link #getLinkedDirectoryFileHeader() CentralDirectoryFileHeader}.
68+ * <br>
69+ * In some cases the {@link LocalFileHeader} file size may be 0, but the authoritative CEN states a non-0 value,
70+ * which you may want to adopt.
71+ */
72+ public void adoptLinkedCentralDirectoryValues () {
73+ if (data != null && linkedDirectoryFileHeader != null ) {
74+ versionNeededToExtract = linkedDirectoryFileHeader .getVersionNeededToExtract ();
75+ generalPurposeBitFlag = linkedDirectoryFileHeader .getGeneralPurposeBitFlag ();
76+ setCompressionMethod (linkedDirectoryFileHeader .getCompressionMethod ());
77+ lastModFileTime = linkedDirectoryFileHeader .getLastModFileTime ();
78+ lastModFileDate = linkedDirectoryFileHeader .getLastModFileDate ();
79+ setCrc32 (linkedDirectoryFileHeader .getCrc32 ());
80+ setCompressedSize (linkedDirectoryFileHeader .getCompressedSize ());
81+ setUncompressedSize (linkedDirectoryFileHeader .getUncompressedSize ());
82+ setFileNameLength (linkedDirectoryFileHeader .getFileNameLength ());
83+ setFileName (data .sliceOf (offset + 30 , fileNameLength ));
84+ extraField = data .sliceOf (offset + 30 + fileNameLength , extraFieldLength );
85+ long fileDataLength ;
86+ if (compressionMethod == STORED ) {
87+ fileDataLength = uncompressedSize ;
88+ } else {
89+ fileDataLength = compressedSize ;
90+ }
91+ fileData = data .sliceOf (offset + 30 + fileNameLength + extraFieldLength , fileDataLength );
92+ }
93+ }
94+
95+ /**
96+ * Clears the reference to the source {@link ByteData}, preventing further modification.
97+ */
98+ public void freeze () {
99+ data = null ;
100+ }
101+
62102 @ Override
63103 public long length () {
64104 return MIN_FIXED_SIZE + fileName .length () + extraField .length () + fileData .length ();
0 commit comments