Skip to content

Commit 6027be7

Browse files
NC-7658: Correctly assemble zip64 files
- Correct zip64 End Headers - Correct zip64 offsets - Update Version Number
1 parent acdf163 commit 6027be7

File tree

9 files changed

+296
-58
lines changed

9 files changed

+296
-58
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ project (lib3MF)
99
# Define Version
1010
set(LIB3MF_VERSION_MAJOR 1) # increase on every backward-compatibility breaking change of the API
1111
set(LIB3MF_VERSION_MINOR 1) # increase on every backward compatible change of the API
12-
set(LIB3MF_VERSION_MICRO 3) # increase on on every change that does not alter the API
12+
set(LIB3MF_VERSION_MICRO 4) # increase on on every change that does not alter the API
1313

1414
set(CMAKE_INSTALL_BINDIR bin CACHE PATH "directory for installing binary files")
1515
set(CMAKE_INSTALL_LIBDIR lib CACHE PATH "directory for installing library files")

Include/Common/NMR_ErrorConst.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,9 @@ NMR_ErrorConst.h defines all error code constants.
272272
// UUID generation failed
273273
#define NMR_ERROR_UUIDGENERATIONFAILED 0x1049
274274

275+
// ZIP Entry too large for non zip64 zip-file
276+
#define NMR_ERROR_ZIPENTRYNON64_TOOLARGE 0x104A
277+
275278
/*-------------------------------------------------------------------
276279
Core framework error codes (0x2XXX)
277280
-------------------------------------------------------------------*/

Include/Common/Platform/NMR_PortableZIPWriter.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,15 @@ namespace NMR {
5151
nfUint32 m_nNextEntryKey;
5252
nfBool m_bIsFinished;
5353

54+
nfBool m_bWriteZIP64;
55+
nfUint16 m_nVersionMade;
56+
nfUint16 m_nVersionNeeded;
57+
5458
std::list<PPortableZIPWriterEntry> m_Entries;
5559
PExportStream m_pCurrentStream;
5660
public:
5761
CPortableZIPWriter() = delete;
58-
CPortableZIPWriter(_In_ PExportStream pExportStream);
62+
CPortableZIPWriter(_In_ PExportStream pExportStream, _In_ nfBool bWriteZIP64);
5963
~CPortableZIPWriter();
6064

6165
PExportStream createEntry(_In_ const std::wstring sName, _In_ nfTimeStamp nUnixTimeStamp);

Include/Common/Platform/NMR_PortableZIPWriterTypes.h

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,13 @@ NMR_PortableZIPWriterTypes.h defines a portable and fast writer of ZIP files
3838
#define ZIPFILEHEADERSIGNATURE 0x04034b50
3939
#define ZIPFILECENTRALHEADERSIGNATURE 0x02014b50
4040
#define ZIPFILEENDOFCENTRALDIRSIGNATURE 0x06054b50
41-
#define ZIPFILEDATADESCRIPTORSIGNATURE 0x08074b5
41+
#define ZIPFILEDATADESCRIPTORSIGNATURE 0x08074b50
4242
#define ZIPFILEDESCRIPTOROFFSET 14
4343
#define ZIPFILEVERSIONNEEDED 10
44+
#define ZIPFILEVERSIONNEEDEDZIP64 0x2D
45+
#define ZIP64FILEENDOFCENTRALDIRRECORDSIGNATURE 0x06064b50
46+
#define ZIP64FILEENDOFCENTRALDIRLOCATORSIGNATURE 0x07064b50
47+
4448
#define ZIPFILEEXTERNALFILEATTRIBUTES 0x80 // faArchive
4549
#define ZIPFILEMAXENTRIES 2147483647 // 2^31 - 1
4650

@@ -52,6 +56,8 @@ NMR_PortableZIPWriterTypes.h defines a portable and fast writer of ZIP files
5256
#define ZIPFILECOMPRESSION_DEFLATED 8
5357
#define ZIPFILEMAXFILENAMELENGTH 32000
5458

59+
#define ZIPFILEMAXIMUMSIZENON64 0xFFFFFFFF
60+
5561
namespace NMR {
5662

5763
#pragma pack (1)
@@ -75,18 +81,13 @@ namespace NMR {
7581
nfUint32 m_nCompressedSize;
7682
nfUint32 m_nUnCompressedSize;
7783
} ZIPLOCALFILEDESCRIPTOR;
78-
79-
typedef struct {
80-
nfUint16 m_nHeaderID;
81-
nfUint16 m_nDataSize;
82-
} ZIPLOCALFILEADDITIONALHEADER;
8384

8485
typedef struct {
86+
nfUint16 m_nTag;
87+
nfUint16 m_nFieldSize;
8588
nfUint64 m_nUncompressedSize;
8689
nfUint64 m_nCompressedSize;
87-
nfUint64 m_nRelativeHeaderOffset;
88-
nfUint32 m_nDiskStartNumber;
89-
} ZIPLOCALFILEEXTENDEDINFORMATIONFIELD;
90+
} ZIP64EXTRAINFORMATIONFIELD;
9091

9192
typedef struct {
9293
nfUint32 m_nSignature;
@@ -119,6 +120,27 @@ namespace NMR {
119120
nfUint16 m_nCommentLength;
120121
} ZIPENDOFCENTRALDIRHEADER;
121122

123+
typedef struct {
124+
nfUint32 m_nSignature;
125+
nfUint64 m_nEndOfCentralDirHeaderRecord;
126+
nfUint16 m_nVersionMade;
127+
nfUint16 m_nVersionNeeded;
128+
nfUint32 m_nNumberOfDisk;
129+
nfUint32 m_nNumberOfDiskOfCentralDirectory;
130+
nfUint64 m_nTotalNumberOfEntriesOnThisDisk;
131+
nfUint64 m_nTotalNumberOfEntriesInCentralDirectory;
132+
nfUint64 m_nSizeOfCentralDirectory;
133+
nfUint64 m_nOffsetOfCentralDirectoryWithRespectToDisk;
134+
// zip64 extensible data sector, variable size; not used
135+
} ZIP64ENDOFCENTRALDIRHEADER;
136+
137+
typedef struct {
138+
nfUint32 m_nSignature;
139+
nfUint32 m_nNumberOfDiskWithStartOfZIP64EOCentralDir;
140+
nfUint64 m_nRelativeOffset;
141+
nfUint32 m_nTotalNumberOfDisk;
142+
} ZIP64ENDOFCENTRALDIRLOCATOR;
143+
122144
#pragma pack()
123145

124146
}

Source/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ set(SRCS_WIN_MANAGEDTEST
4141
./Source/UnitTests/UnitTest_MeshFormat_STL.cpp
4242
./Source/UnitTests/UnitTest_Model.cpp
4343
./Source/UnitTests/UnitTest_ModelFactory.cpp
44+
./Source/UnitTests/UnitTest_ZIP.cpp
4445
)
4546

4647
set(SRCS_UNIX_MAIN

Source/Common/NMR_Exception.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ namespace NMR {
123123
case NMR_ERROR_INVALIDRELATIONSHIPTYPEFORTEXTURE: return "A texture must use a OPC part with relationshiptype 3D Texture.";
124124
case NMR_ERROR_IMPORTSTREAMISEMPTY: return "An attachment to be read does coes not have any content.";
125125
case NMR_ERROR_UUIDGENERATIONFAILED: return "Generation of a UUID failed.";
126+
case NMR_ERROR_ZIPENTRYNON64_TOOLARGE: return "A ZIP Entry is too large for non zip64 zip-file";
126127

127128

128129
// Unhandled exception

Source/Common/OPC/NMR_OpcPackageWriter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ namespace NMR {
4747
throw CNMRException(NMR_ERROR_INVALIDPARAM);
4848

4949
m_pExportStream = pExportStream;
50-
m_pZIPWriter = std::make_shared<CPortableZIPWriter>(m_pExportStream);
50+
m_pZIPWriter = std::make_shared<CPortableZIPWriter>(m_pExportStream, true);
5151
}
5252

5353
COpcPackageWriter::~COpcPackageWriter()

Source/Common/Platform/NMR_PortableZIPWriter.cpp

Lines changed: 107 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*++
22
3+
Copyright (C) 2018 Autodesk Inc.
34
Copyright (C) 2015 netfabb GmbH (Original Author)
45
56
All rights reserved.
@@ -37,7 +38,7 @@ NMR_PortableZIPWriter.cpp implements a portable and fast writer of ZIP files
3738

3839
namespace NMR {
3940

40-
CPortableZIPWriter::CPortableZIPWriter(_In_ PExportStream pExportStream)
41+
CPortableZIPWriter::CPortableZIPWriter(_In_ PExportStream pExportStream, _In_ nfBool bWriteZIP64)
4142
{
4243
if (pExportStream.get() == nullptr)
4344
throw CNMRException(NMR_ERROR_INVALIDPARAM);
@@ -47,16 +48,26 @@ namespace NMR {
4748
m_nNextEntryKey = 1;
4849
m_pCurrentEntry = nullptr;
4950
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+
}
5061

5162
if (m_pExportStream->getPosition() != 0)
5263
throw CNMRException(NMR_ERROR_EXPORTSTREAMNOTEMPTY);
64+
5365
}
5466

5567
CPortableZIPWriter::~CPortableZIPWriter()
5668
{
5769
if (!m_bIsFinished)
5870
writeDirectory();
59-
6071
}
6172

6273
PExportStream CPortableZIPWriter::createEntry(_In_ const std::wstring sName, _In_ nfTimeStamp nUnixTimeStamp)
@@ -87,7 +98,7 @@ namespace NMR {
8798
// Write local file header
8899
ZIPLOCALFILEHEADER LocalHeader;
89100
LocalHeader.m_nSignature = ZIPFILEHEADERSIGNATURE;
90-
LocalHeader.m_nVersion = ZIPFILEVERSIONNEEDED;
101+
LocalHeader.m_nVersion = m_nVersionNeeded;
91102
LocalHeader.m_nGeneralPurposeFlags = 0;
92103
LocalHeader.m_nCompressionMethod = ZIPFILECOMPRESSION_DEFLATED;
93104
LocalHeader.m_nLastModTime = nLastModTime;
@@ -98,24 +109,23 @@ namespace NMR {
98109
LocalHeader.m_nFileNameLength = nNameLength;
99110
LocalHeader.m_nExtraFieldLength = 0;// sizeof(ZIPLOCALFILEADDITIONALHEADER) + sizeof(ZIPLOCALFILEEXTENDEDINFORMATIONFIELD);
100111

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+
}
104115

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;
110121

111122
// Write data to ZIP stream
112123
nfUint64 nFilePosition = m_pExportStream->getPosition();
113124
m_pExportStream->writeBuffer(&LocalHeader, sizeof(LocalHeader));
114125
m_pExportStream->writeBuffer(sUTF8Name.c_str(), nNameLength);
115-
//m_pExportStream->writeBuffer(&AdditionalHeader, sizeof(AdditionalHeader));
116-
117126
nfUint64 nExtInfoPosition = m_pExportStream->getPosition();
118-
//m_pExportStream->writeBuffer(&ExtendedInformation, sizeof(ExtendedInformation));
127+
if (m_bWriteZIP64)
128+
m_pExportStream->writeBuffer(&zip64ExtraInformation, sizeof(zip64ExtraInformation));
119129

120130
nfUint64 nDataPosition = m_pExportStream->getPosition();
121131

@@ -143,24 +153,34 @@ namespace NMR {
143153
// Write CRC and Size
144154
ZIPLOCALFILEDESCRIPTOR FileDescriptor;
145155
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+
149174
// Write File Descriptor to file
150175
m_pExportStream->seekPosition(m_pCurrentEntry->getFilePosition() + ZIPFILEDESCRIPTOROFFSET, true);
151176
m_pExportStream->writeBuffer(&FileDescriptor, sizeof(FileDescriptor));
152177

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+
164184
// Reset file pointer
165185
m_pExportStream->seekFromEnd(0, true);
166186
}
@@ -226,44 +246,80 @@ namespace NMR {
226246
PPortableZIPWriterEntry pEntry = *iIterator;
227247
std::string sUTF8Name = pEntry->getUTF8Name();
228248
nfUint32 nNameLength = (nfUint32)sUTF8Name.length();
229-
249+
230250
ZIPCENTRALDIRECTORYFILEHEADER DirectoryHeader;
231251
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;
234254
DirectoryHeader.m_nGeneralPurposeFlags = 0;
235255
DirectoryHeader.m_nCompressionMethod = ZIPFILECOMPRESSION_DEFLATED;
236256
DirectoryHeader.m_nLastModTime = pEntry->getLastModTime();
237257
DirectoryHeader.m_nLastModDate = pEntry->getLastModDate();
238258
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;
241261
DirectoryHeader.m_nFileNameLength = nNameLength;
242-
DirectoryHeader.m_nExtraFieldLength = 0;//sizeof(ZIPLOCALFILEADDITIONALHEADER) + sizeof(ZIPLOCALFILEEXTENDEDINFORMATIONFIELD);
262+
DirectoryHeader.m_nExtraFieldLength = 0;
243263
DirectoryHeader.m_nFileCommentLength = 0;
244264
DirectoryHeader.m_nDiskNumberStart = 0;
245265
DirectoryHeader.m_nInternalFileAttributes = 0;
246266
DirectoryHeader.m_nExternalFileAttributes = ZIPFILEEXTERNALFILEATTRIBUTES;
247267
DirectoryHeader.m_nRelativeOffsetOfLocalHeader = (nfUint32) pEntry->getFilePosition();
248268

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+
}
258283

259284
m_pExportStream->writeBuffer(&DirectoryHeader, (nfUint64) sizeof(DirectoryHeader));
260285
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+
264298
iIterator++;
265299
}
266300

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+
267323
ZIPENDOFCENTRALDIRHEADER EndHeader;
268324
EndHeader.m_nSignature = ZIPFILEENDOFCENTRALDIRSIGNATURE;
269325
EndHeader.m_nNumberOfDisk = 0;
@@ -274,6 +330,11 @@ namespace NMR {
274330
EndHeader.m_nOffsetOfCentralDirectory = (nfUint32)nCentralDirStartPos;
275331
EndHeader.m_nCommentLength = 0;
276332

333+
if (m_bWriteZIP64) {
334+
EndHeader.m_nOffsetOfCentralDirectory = 0xFFFFFFFF;
335+
m_pExportStream->writeBuffer(&EndHeader64, sizeof(EndHeader64));
336+
m_pExportStream->writeBuffer(&EndLocator64, sizeof(EndLocator64));
337+
}
277338
m_pExportStream->writeBuffer(&EndHeader, (nfUint64) sizeof(EndHeader));
278339

279340
m_bIsFinished = true;

0 commit comments

Comments
 (0)