Skip to content

Commit 3eeb626

Browse files
feat(PLAT-3087): zip reader-writer (#23)
Implement reading zip (tdf) file from the end --------- Co-authored-by: sujankota <sreddy@virtru.com>
1 parent 64c16a2 commit 3eeb626

File tree

6 files changed

+796
-0
lines changed

6 files changed

+796
-0
lines changed

sdk/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,11 @@
5757
<version>5.0.0-alpha.14</version>
5858
<scope>test</scope>
5959
</dependency>
60+
<dependency>
61+
<groupId>junit</groupId>
62+
<artifactId>junit</artifactId>
63+
<version>4.13.1</version>
64+
<scope>test</scope>
65+
</dependency>
6066
</dependencies>
6167
</project>
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
package io.opentdf.platform.sdk;
2+
3+
import java.nio.ByteBuffer;
4+
import java.nio.ByteOrder;
5+
import java.nio.charset.StandardCharsets;
6+
7+
public class ZipReader {
8+
private static final int END_OF_CENTRAL_DIRECTORY_SIGNATURE = 0x06054b50;
9+
private static final int ZIP64_END_OF_CENTRAL_DIRECTORY_SIGNATURE = 0x06064b50;
10+
private static final int ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIGNATURE = 0x07064b50;
11+
private static final int CENTRAL_DIRECTORY_LOCATOR_SIGNATURE = 0x02014b50;
12+
private static final int LOCAL_FILE_HEADER_SIGNATURE = 0x04034b50;
13+
private static final int ZIP64_MAGICVAL = 0xFFFFFFFF;
14+
private static final int ZIP64_EXTID= 0x0001;
15+
16+
private int numEntries;
17+
private short fileNameLength;
18+
private short extraFieldLength;
19+
private long offsetToStartOfCentralDirectory;
20+
private long relativeOffsetEndOfZip64EndOfCentralDirectory;
21+
22+
public void readEndOfCentralDirectory(ByteBuffer buffer) throws Exception {
23+
buffer.order(ByteOrder.LITTLE_ENDIAN);
24+
long fileSize = buffer.capacity();
25+
long pointer = fileSize - 22; // 22 is the minimum size of the EOCDR
26+
27+
// Search for the EOCDR from the end of the file
28+
while (pointer >= 0) {
29+
buffer.position((int)pointer);
30+
int signature = buffer.getInt();
31+
if (signature == END_OF_CENTRAL_DIRECTORY_SIGNATURE) {
32+
System.out.println("Found End of Central Directory Record");
33+
break;
34+
}
35+
pointer--;
36+
}
37+
38+
if (pointer < 0) {
39+
throw new Exception("Invalid tdf file");
40+
}
41+
42+
// Read the EOCDR
43+
short diskNumber = buffer.getShort();
44+
short centralDirectoryDiskNumber = buffer.getShort();
45+
short numEntriesThisDisk = buffer.getShort();
46+
numEntries = buffer.getShort();
47+
int centralDirectorySize = buffer.getInt();
48+
offsetToStartOfCentralDirectory = buffer.getInt();
49+
short commentLength = buffer.getShort();
50+
51+
// buffer's position at the start of the Central Directory
52+
boolean isZip64 = false;
53+
if (offsetToStartOfCentralDirectory != ZIP64_MAGICVAL) {
54+
//buffer.position((int)offsetToStartOfCentralDirectory);
55+
} else {
56+
isZip64 = true;
57+
long index = fileSize - (22+ 20); // 22 is the size of the EOCDR and 20 is the size of the Zip64 EOCDR
58+
buffer.position((int)index);
59+
readZip64EndOfCentralDirectoryLocator(buffer);
60+
index = fileSize - (22 + 20 + 56); // 56 is the size of the Zip64 EOCDR
61+
buffer.position((int)index);
62+
readZip64EndOfCentralDirectoryRecord(buffer);
63+
//buffer.position((int)offsetToStartOfCentralDirectory);
64+
}
65+
// buffer.position(centralDirectoryOffset);
66+
}
67+
68+
private void readZip64EndOfCentralDirectoryLocator(ByteBuffer buffer) {
69+
int signature = buffer.getInt() ;
70+
if (signature != ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIGNATURE) {
71+
throw new RuntimeException("Invalid Zip64 End of Central Directory Record Signature");
72+
}
73+
int numberOfDiskWithZip64End = buffer.getInt();
74+
relativeOffsetEndOfZip64EndOfCentralDirectory = buffer.getLong();
75+
int totalNumberOfDisks = buffer.getInt();
76+
}
77+
78+
private void readZip64EndOfCentralDirectoryRecord(ByteBuffer buffer) {
79+
int signature = buffer.getInt() ;
80+
if (signature != ZIP64_END_OF_CENTRAL_DIRECTORY_SIGNATURE) {
81+
throw new RuntimeException("Invalid Zip64 End of Central Directory Record ");
82+
}
83+
long sizeOfZip64EndOfCentralDirectoryRecord = buffer.getLong();
84+
short versionMadeBy = buffer.getShort();
85+
short versionNeededToExtract = buffer.getShort();
86+
int diskNumber = buffer.getInt();
87+
int diskWithCentralDirectory = buffer.getInt();
88+
long numEntriesOnThisDisk = buffer.getLong();
89+
numEntries = (int)buffer.getLong();
90+
long centralDirectorySize = buffer.getLong();
91+
offsetToStartOfCentralDirectory = buffer.getLong();
92+
}
93+
94+
public int getNumEntries() {
95+
return numEntries;
96+
}
97+
98+
public short getFileNameLength() {
99+
return fileNameLength;
100+
}
101+
102+
public short getExtraFieldLength() {
103+
return extraFieldLength;
104+
}
105+
106+
public long getCDOffset() {
107+
return offsetToStartOfCentralDirectory;
108+
}
109+
110+
public long readCentralDirectoryFileHeader(ByteBuffer buffer) {
111+
System.out.println("Buffer position: " + buffer.position());
112+
int signature = buffer.getInt();
113+
if (signature != CENTRAL_DIRECTORY_LOCATOR_SIGNATURE) {
114+
throw new RuntimeException("Invalid Central Directory File Header Signature");
115+
}
116+
short versionMadeBy = buffer.getShort();
117+
short versionNeededToExtract = buffer.getShort();
118+
short generalPurposeBitFlag = buffer.getShort();
119+
short compressionMethod = buffer.getShort();
120+
short lastModFileTime = buffer.getShort();
121+
short lastModFileDate = buffer.getShort();
122+
int crc32 = buffer.getInt();
123+
int compressedSize = buffer.getInt();
124+
int uncompressedSize = buffer.getInt();
125+
fileNameLength = buffer.getShort();
126+
extraFieldLength = buffer.getShort();
127+
short fileCommentLength = buffer.getShort();
128+
short diskNumberStart = buffer.getShort();
129+
short internalFileAttributes = buffer.getShort();
130+
int externalFileAttributes = buffer.getInt();
131+
long relativeOffsetOfLocalHeader = buffer.getInt() ;
132+
133+
byte[] fileName = new byte[fileNameLength];
134+
buffer.get(fileName);
135+
String fileNameString = new String(fileName, StandardCharsets.UTF_8);
136+
////
137+
if (compressedSize == ZIP64_MAGICVAL || uncompressedSize == ZIP64_MAGICVAL || relativeOffsetOfLocalHeader == ZIP64_MAGICVAL) {
138+
// Parse the extra field
139+
for (int i = 0; i < extraFieldLength; ) {
140+
int headerId = buffer.getShort();
141+
int dataSize = buffer.getShort();
142+
i += 4;
143+
144+
if (headerId == ZIP64_EXTID) {
145+
if (compressedSize == ZIP64_MAGICVAL) {
146+
compressedSize = (int)buffer.getLong();
147+
i += 8;
148+
}
149+
if (uncompressedSize == ZIP64_MAGICVAL) {
150+
uncompressedSize = (int)buffer.getLong();
151+
i += 8;
152+
}
153+
if (relativeOffsetOfLocalHeader == ZIP64_MAGICVAL) {
154+
relativeOffsetOfLocalHeader = buffer.getLong();
155+
i += 8;
156+
}
157+
} else {
158+
// Skip other extra fields
159+
buffer.position(buffer.position() + dataSize);
160+
i += dataSize;
161+
}
162+
}
163+
}
164+
////
165+
byte[] extraField = new byte[extraFieldLength];
166+
buffer.get(extraField);
167+
168+
byte[] fileComment = new byte[fileCommentLength];
169+
buffer.get(fileComment);
170+
String fileCommentString = new String(fileComment, StandardCharsets.UTF_8);
171+
return relativeOffsetOfLocalHeader;
172+
}
173+
174+
public void readLocalFileHeader(ByteBuffer buffer) {
175+
int signature = buffer.getInt();
176+
if (signature != LOCAL_FILE_HEADER_SIGNATURE) {
177+
throw new RuntimeException("Invalid Local File Header Signature");
178+
}
179+
short versionNeededToExtract = buffer.getShort();
180+
short generalPurposeBitFlag = buffer.getShort();
181+
short compressionMethod = buffer.getShort();
182+
short lastModFileTime = buffer.getShort();
183+
short lastModFileDate = buffer.getShort();
184+
int crc32 = buffer.getInt();
185+
int compressedSize = buffer.getInt();
186+
int uncompressedSize = buffer.getInt();
187+
short fileNameLength = buffer.getShort();
188+
short extraFieldLength = buffer.getShort();
189+
190+
byte[] fileName = new byte[fileNameLength];
191+
buffer.get(fileName);
192+
String fileNameString = new String(fileName, StandardCharsets.UTF_8);
193+
System.out.println("File name: " + fileNameString);
194+
195+
byte[] extraField = new byte[extraFieldLength];
196+
buffer.get(extraField);
197+
198+
/*byte[] fileData = new byte[compressedSize];
199+
buffer.get(fileData);
200+
201+
if (compressionMethod == 0) {
202+
String fileContent = new String(fileData, StandardCharsets.UTF_8);
203+
System.out.println("File content: " + fileContent);
204+
} else {
205+
System.out.println("File is compressed, need to decompress it first");
206+
}*/
207+
}
208+
}

0 commit comments

Comments
 (0)