1
1
/* ++
2
2
3
+ Copyright (C) 2018 Autodesk Inc.
3
4
Copyright (C) 2015 netfabb GmbH (Original Author)
4
5
5
6
All rights reserved.
@@ -37,7 +38,7 @@ NMR_PortableZIPWriter.cpp implements a portable and fast writer of ZIP files
37
38
38
39
namespace NMR {
39
40
40
- CPortableZIPWriter::CPortableZIPWriter (_In_ PExportStream pExportStream)
41
+ CPortableZIPWriter::CPortableZIPWriter (_In_ PExportStream pExportStream, _In_ nfBool bWriteZIP64 )
41
42
{
42
43
if (pExportStream.get () == nullptr )
43
44
throw CNMRException (NMR_ERROR_INVALIDPARAM);
@@ -47,16 +48,26 @@ namespace NMR {
47
48
m_nNextEntryKey = 1 ;
48
49
m_pCurrentEntry = nullptr ;
49
50
m_bIsFinished = false ;
51
+ m_bWriteZIP64 = bWriteZIP64;
52
+
53
+ if (m_bWriteZIP64) {
54
+ m_nVersionMade = ZIPFILEVERSIONNEEDEDZIP64;
55
+ m_nVersionNeeded = ZIPFILEVERSIONNEEDEDZIP64;
56
+ }
57
+ else {
58
+ m_nVersionMade = ZIPFILEVERSIONNEEDED;
59
+ m_nVersionNeeded = ZIPFILEVERSIONNEEDED;
60
+ }
50
61
51
62
if (m_pExportStream->getPosition () != 0 )
52
63
throw CNMRException (NMR_ERROR_EXPORTSTREAMNOTEMPTY);
64
+
53
65
}
54
66
55
67
CPortableZIPWriter::~CPortableZIPWriter ()
56
68
{
57
69
if (!m_bIsFinished)
58
70
writeDirectory ();
59
-
60
71
}
61
72
62
73
PExportStream CPortableZIPWriter::createEntry (_In_ const std::wstring sName , _In_ nfTimeStamp nUnixTimeStamp)
@@ -87,7 +98,7 @@ namespace NMR {
87
98
// Write local file header
88
99
ZIPLOCALFILEHEADER LocalHeader;
89
100
LocalHeader.m_nSignature = ZIPFILEHEADERSIGNATURE;
90
- LocalHeader.m_nVersion = ZIPFILEVERSIONNEEDED ;
101
+ LocalHeader.m_nVersion = m_nVersionNeeded ;
91
102
LocalHeader.m_nGeneralPurposeFlags = 0 ;
92
103
LocalHeader.m_nCompressionMethod = ZIPFILECOMPRESSION_DEFLATED;
93
104
LocalHeader.m_nLastModTime = nLastModTime;
@@ -98,24 +109,23 @@ namespace NMR {
98
109
LocalHeader.m_nFileNameLength = nNameLength;
99
110
LocalHeader.m_nExtraFieldLength = 0 ;// sizeof(ZIPLOCALFILEADDITIONALHEADER) + sizeof(ZIPLOCALFILEEXTENDEDINFORMATIONFIELD);
100
111
101
- /* ZIPLOCALFILEADDITIONALHEADER AdditionalHeader;
102
- AdditionalHeader.m_nHeaderID = ZIPFILEDATAZIP64EXTENDEDINFORMATIONEXTRAFIELD ;
103
- AdditionalHeader.m_nDataSize = sizeof(ZIPLOCALFILEEXTENDEDINFORMATIONFIELD);
112
+ if (m_bWriteZIP64) {
113
+ LocalHeader. m_nExtraFieldLength += sizeof (ZIP64EXTRAINFORMATIONFIELD) ;
114
+ }
104
115
105
- ZIPLOCALFILEEXTENDEDINFORMATIONFIELD ExtendedInformation ;
106
- ExtendedInformation.m_nCompressedSize = 0 ;
107
- ExtendedInformation.m_nUncompressedSize = 0 ;
108
- ExtendedInformation.m_nDiskStartNumber = 0;
109
- ExtendedInformation.m_nRelativeHeaderOffset = 0; */
116
+ ZIP64EXTRAINFORMATIONFIELD zip64ExtraInformation ;
117
+ zip64ExtraInformation. m_nTag = ZIPFILEDATAZIP64EXTENDEDINFORMATIONEXTRAFIELD ;
118
+ zip64ExtraInformation. m_nFieldSize = sizeof (ZIP64EXTRAINFORMATIONFIELD) - 4 ;
119
+ zip64ExtraInformation. m_nCompressedSize = 0 ;
120
+ zip64ExtraInformation. m_nUncompressedSize = 0 ;
110
121
111
122
// Write data to ZIP stream
112
123
nfUint64 nFilePosition = m_pExportStream->getPosition ();
113
124
m_pExportStream->writeBuffer (&LocalHeader, sizeof (LocalHeader));
114
125
m_pExportStream->writeBuffer (sUTF8Name .c_str (), nNameLength);
115
- // m_pExportStream->writeBuffer(&AdditionalHeader, sizeof(AdditionalHeader));
116
-
117
126
nfUint64 nExtInfoPosition = m_pExportStream->getPosition ();
118
- // m_pExportStream->writeBuffer(&ExtendedInformation, sizeof(ExtendedInformation));
127
+ if (m_bWriteZIP64)
128
+ m_pExportStream->writeBuffer (&zip64ExtraInformation, sizeof (zip64ExtraInformation));
119
129
120
130
nfUint64 nDataPosition = m_pExportStream->getPosition ();
121
131
@@ -143,24 +153,34 @@ namespace NMR {
143
153
// Write CRC and Size
144
154
ZIPLOCALFILEDESCRIPTOR FileDescriptor;
145
155
FileDescriptor.m_nCRC32 = m_pCurrentEntry->getCRC32 ();
146
- FileDescriptor.m_nCompressedSize = (nfUint32) m_pCurrentEntry->getCompressedSize ();
147
- FileDescriptor.m_nUnCompressedSize = (nfUint32) m_pCurrentEntry->getUncompressedSize ();
148
-
156
+ if (m_bWriteZIP64) {
157
+ FileDescriptor.m_nCompressedSize =0xFFFFFFFF ;
158
+ FileDescriptor.m_nUnCompressedSize = 0xFFFFFFFF ;
159
+ }
160
+ else {
161
+ if ((m_pCurrentEntry->getCompressedSize () > ZIPFILEMAXIMUMSIZENON64) ||
162
+ (m_pCurrentEntry->getUncompressedSize () > ZIPFILEMAXIMUMSIZENON64))
163
+ throw CNMRException (NMR_ERROR_ZIPENTRYNON64_TOOLARGE);
164
+ FileDescriptor.m_nCompressedSize = (nfUint32)m_pCurrentEntry->getCompressedSize ();
165
+ FileDescriptor.m_nUnCompressedSize = (nfUint32)m_pCurrentEntry->getUncompressedSize ();
166
+ }
167
+
168
+ ZIP64EXTRAINFORMATIONFIELD zip64ExtraInformation;
169
+ zip64ExtraInformation.m_nTag = ZIPFILEDATAZIP64EXTENDEDINFORMATIONEXTRAFIELD;
170
+ zip64ExtraInformation.m_nFieldSize = sizeof (ZIP64EXTRAINFORMATIONFIELD) - 4 ;
171
+ zip64ExtraInformation.m_nCompressedSize = m_pCurrentEntry->getCompressedSize ();
172
+ zip64ExtraInformation.m_nUncompressedSize = m_pCurrentEntry->getUncompressedSize ();
173
+
149
174
// Write File Descriptor to file
150
175
m_pExportStream->seekPosition (m_pCurrentEntry->getFilePosition () + ZIPFILEDESCRIPTOROFFSET, true );
151
176
m_pExportStream->writeBuffer (&FileDescriptor, sizeof (FileDescriptor));
152
177
153
- // Write Extended Information to file
154
- /* ZIPLOCALFILEEXTENDEDINFORMATIONFIELD ExtendedInformation;
155
- ExtendedInformation.m_nCompressedSize = m_pCurrentEntry->getCompressedSize();
156
- ExtendedInformation.m_nUncompressedSize = m_pCurrentEntry->getUncompressedSize();
157
- ExtendedInformation.m_nDiskStartNumber = 0;
158
- ExtendedInformation.m_nRelativeHeaderOffset = m_pCurrentEntry->getFilePosition();
159
-
160
- // Write Info Table
161
- m_pExportStream->seekPosition(m_pCurrentEntry->getExtInfoPosition(), true);
162
- //m_pExportStream->writeBuffer(&ExtendedInformation, sizeof(ExtendedInformation));
163
- */
178
+ if (m_bWriteZIP64) {
179
+ // Write Extra Information to file
180
+ m_pExportStream->seekPosition (m_pCurrentEntry->getExtInfoPosition (), true );
181
+ m_pExportStream->writeBuffer (&zip64ExtraInformation, sizeof (zip64ExtraInformation));
182
+ }
183
+
164
184
// Reset file pointer
165
185
m_pExportStream->seekFromEnd (0 , true );
166
186
}
@@ -226,44 +246,80 @@ namespace NMR {
226
246
PPortableZIPWriterEntry pEntry = *iIterator;
227
247
std::string sUTF8Name = pEntry->getUTF8Name ();
228
248
nfUint32 nNameLength = (nfUint32)sUTF8Name .length ();
229
-
249
+
230
250
ZIPCENTRALDIRECTORYFILEHEADER DirectoryHeader;
231
251
DirectoryHeader.m_nSignature = ZIPFILECENTRALHEADERSIGNATURE;
232
- DirectoryHeader.m_nVersionMade = ZIPFILEVERSIONNEEDED ;
233
- DirectoryHeader.m_nVersionNeeded = ZIPFILEVERSIONNEEDED ;
252
+ DirectoryHeader.m_nVersionMade = m_nVersionMade ;
253
+ DirectoryHeader.m_nVersionNeeded = m_nVersionNeeded ;
234
254
DirectoryHeader.m_nGeneralPurposeFlags = 0 ;
235
255
DirectoryHeader.m_nCompressionMethod = ZIPFILECOMPRESSION_DEFLATED;
236
256
DirectoryHeader.m_nLastModTime = pEntry->getLastModTime ();
237
257
DirectoryHeader.m_nLastModDate = pEntry->getLastModDate ();
238
258
DirectoryHeader.m_nCRC32 = pEntry->getCRC32 ();
239
- DirectoryHeader.m_nCompressedSize = (nfUint32) pEntry-> getCompressedSize () ;
240
- DirectoryHeader.m_nUnCompressedSize = (nfUint32) pEntry-> getUncompressedSize () ;
259
+ DirectoryHeader.m_nCompressedSize = 0 ;
260
+ DirectoryHeader.m_nUnCompressedSize = 0 ;
241
261
DirectoryHeader.m_nFileNameLength = nNameLength;
242
- DirectoryHeader.m_nExtraFieldLength = 0 ;// sizeof(ZIPLOCALFILEADDITIONALHEADER) + sizeof(ZIPLOCALFILEEXTENDEDINFORMATIONFIELD);
262
+ DirectoryHeader.m_nExtraFieldLength = 0 ;
243
263
DirectoryHeader.m_nFileCommentLength = 0 ;
244
264
DirectoryHeader.m_nDiskNumberStart = 0 ;
245
265
DirectoryHeader.m_nInternalFileAttributes = 0 ;
246
266
DirectoryHeader.m_nExternalFileAttributes = ZIPFILEEXTERNALFILEATTRIBUTES;
247
267
DirectoryHeader.m_nRelativeOffsetOfLocalHeader = (nfUint32) pEntry->getFilePosition ();
248
268
249
- /* ZIPLOCALFILEADDITIONALHEADER AdditionalHeader;
250
- AdditionalHeader.m_nHeaderID = ZIPFILEDATAZIP64EXTENDEDINFORMATIONEXTRAFIELD;
251
- AdditionalHeader.m_nDataSize = sizeof(ZIPLOCALFILEEXTENDEDINFORMATIONFIELD);
252
-
253
- ZIPLOCALFILEEXTENDEDINFORMATIONFIELD ExtendedInformation;
254
- ExtendedInformation.m_nCompressedSize = pEntry->getCompressedSize();
255
- ExtendedInformation.m_nUncompressedSize = pEntry->getUncompressedSize();
256
- ExtendedInformation.m_nDiskStartNumber = 0;
257
- ExtendedInformation.m_nRelativeHeaderOffset = 0; */
269
+ nfUint64 nRelativeOffsetOfLocalHeader = pEntry->getFilePosition ();
270
+ if (m_bWriteZIP64) {
271
+ DirectoryHeader.m_nCompressedSize = 0xFFFFFFFF ;
272
+ DirectoryHeader.m_nUnCompressedSize = 0xFFFFFFFF ;
273
+ DirectoryHeader.m_nExtraFieldLength += sizeof (ZIP64EXTRAINFORMATIONFIELD) + sizeof (nRelativeOffsetOfLocalHeader);
274
+ DirectoryHeader.m_nRelativeOffsetOfLocalHeader = 0xFFFFFFFF ;
275
+ }
276
+ else {
277
+ if ((m_pCurrentEntry->getCompressedSize () > ZIPFILEMAXIMUMSIZENON64) ||
278
+ (m_pCurrentEntry->getUncompressedSize () > ZIPFILEMAXIMUMSIZENON64))
279
+ throw CNMRException (NMR_ERROR_ZIPENTRYNON64_TOOLARGE);
280
+ DirectoryHeader.m_nCompressedSize = (nfUint32)pEntry->getCompressedSize ();
281
+ DirectoryHeader.m_nUnCompressedSize = (nfUint32)pEntry->getUncompressedSize ();
282
+ }
258
283
259
284
m_pExportStream->writeBuffer (&DirectoryHeader, (nfUint64) sizeof (DirectoryHeader));
260
285
m_pExportStream->writeBuffer (sUTF8Name .c_str (), nNameLength);
261
- // m_pExportStream->writeBuffer(&AdditionalHeader, sizeof(AdditionalHeader));
262
- // m_pExportStream->writeBuffer(&ExtendedInformation, sizeof(ExtendedInformation));
263
-
286
+
287
+ if (m_bWriteZIP64) {
288
+ ZIP64EXTRAINFORMATIONFIELD zip64ExtraInformation;
289
+ zip64ExtraInformation.m_nTag = ZIPFILEDATAZIP64EXTENDEDINFORMATIONEXTRAFIELD;
290
+ zip64ExtraInformation.m_nFieldSize = sizeof (ZIP64EXTRAINFORMATIONFIELD) - 4 + sizeof (nRelativeOffsetOfLocalHeader);
291
+ zip64ExtraInformation.m_nCompressedSize = pEntry->getCompressedSize ();
292
+ zip64ExtraInformation.m_nUncompressedSize = pEntry->getUncompressedSize ();
293
+
294
+ m_pExportStream->writeBuffer (&zip64ExtraInformation, sizeof (zip64ExtraInformation));
295
+ m_pExportStream->writeBuffer (&nRelativeOffsetOfLocalHeader, sizeof (nRelativeOffsetOfLocalHeader));
296
+ }
297
+
264
298
iIterator++;
265
299
}
266
300
301
+ nfUint64 nEndOfCentralDir64StartPos = m_pExportStream->getPosition ();
302
+
303
+ // [ZIP64 end of central directory record]
304
+ ZIP64ENDOFCENTRALDIRHEADER EndHeader64;
305
+ EndHeader64.m_nSignature = ZIP64FILEENDOFCENTRALDIRRECORDSIGNATURE;
306
+ EndHeader64.m_nEndOfCentralDirHeaderRecord = (nfUint64)(sizeof (ZIP64ENDOFCENTRALDIRHEADER) - 12 );
307
+ EndHeader64.m_nVersionMade = m_nVersionMade;
308
+ EndHeader64.m_nVersionNeeded = m_nVersionNeeded;
309
+ EndHeader64.m_nNumberOfDisk = 0 ;
310
+ EndHeader64.m_nNumberOfDiskOfCentralDirectory = 0 ;
311
+ EndHeader64.m_nTotalNumberOfEntriesOnThisDisk = m_Entries.size ();
312
+ EndHeader64.m_nTotalNumberOfEntriesInCentralDirectory = m_Entries.size ();
313
+ EndHeader64.m_nSizeOfCentralDirectory = (nfUint64)(m_pExportStream->getPosition () - nCentralDirStartPos);
314
+ EndHeader64.m_nOffsetOfCentralDirectoryWithRespectToDisk = nCentralDirStartPos;
315
+
316
+ // [ZIP64 end of central directory locator]
317
+ ZIP64ENDOFCENTRALDIRLOCATOR EndLocator64;
318
+ EndLocator64.m_nSignature = ZIP64FILEENDOFCENTRALDIRLOCATORSIGNATURE;
319
+ EndLocator64.m_nNumberOfDiskWithStartOfZIP64EOCentralDir = 0 ;
320
+ EndLocator64.m_nTotalNumberOfDisk = 1 ;
321
+ EndLocator64.m_nRelativeOffset = nEndOfCentralDir64StartPos;
322
+
267
323
ZIPENDOFCENTRALDIRHEADER EndHeader;
268
324
EndHeader.m_nSignature = ZIPFILEENDOFCENTRALDIRSIGNATURE;
269
325
EndHeader.m_nNumberOfDisk = 0 ;
@@ -274,6 +330,11 @@ namespace NMR {
274
330
EndHeader.m_nOffsetOfCentralDirectory = (nfUint32)nCentralDirStartPos;
275
331
EndHeader.m_nCommentLength = 0 ;
276
332
333
+ if (m_bWriteZIP64) {
334
+ EndHeader.m_nOffsetOfCentralDirectory = 0xFFFFFFFF ;
335
+ m_pExportStream->writeBuffer (&EndHeader64, sizeof (EndHeader64));
336
+ m_pExportStream->writeBuffer (&EndLocator64, sizeof (EndLocator64));
337
+ }
277
338
m_pExportStream->writeBuffer (&EndHeader, (nfUint64) sizeof (EndHeader));
278
339
279
340
m_bIsFinished = true ;
0 commit comments