I noticed a few problems with the new pack-implementation (tested with 5.41 and 5.42beta1 x86):
- zip files created violate the zip-specification
- >>DataDescriptor shouldn't be used at all
- >>CRC32 is set although DataDescriptor is present
- >> CompressedSize in LocalFileHeader and CentralDirectoryHeader is wrong
- AddPackFile and CompressMemory generate different results (when comparing only the data section)
- cannot unpack zip file created with windows-zip-implementation
The example below creates a small textfile and add it to a zip file - to check for the problems you need to open the created zip file with a hex editor - basically you should see this:

In APPNOTE :
4.3.9 Data descriptor:
4.3.9.1 This descriptor MUST exist if bit 3 of the general purpose bit flag is set (see below). It is byte aligned and immediately follows the last byte of compressed data. This descriptor SHOULD be used only when it was not possible to seek in the output .ZIP file, e.g., when the output .ZIP file was standard output or a non-seekable device.
section 4.4.4 general purpose bit flag it says 'Bit 3: If this bit is set, the fields crc-32, compressed size and uncompressed size are set to zero in the local header. The correct values are put in the data descriptor immediately following the compressed data.
So as far as I can see the DataDescriptor shouldn't be used at all - because my harddrive is seekable and I don't think that purebasic even supports non seekable devices4.4.7 CRC-32: (4 bytes)' : 'If bit 3 of the general purpose flag is set, this field is set to zero in the local header and the correct value is put in the data descriptor and in the central directory.

But in case it is used the CRC32 in the LocalFileHeader has to be set to 0 - otherwise it violates the specification.
The next problem I've noticed is that the 'CompressedSize' is set to 0x10 bytes in the DataDescriptor and in the CentralDirectoryHeader - but the CompressedData is in fact 0x30 bytes long!
The next thing I've tried is to simply compress the Inputfile used before with 'CompressMemory' and write the compressed memory to a file - and the interesting thing is, that this file now has 0x16 bytes in size - so the 'CompressMemory' compresses different than the 'AddPackFile' ? Basically I'd expected that both data sections (the one in the zip archive and the pure 'compressmemory' file) are completely identical as both use the '
UseZipPacker()' functionality.
I also noticed that when I cannot uncompress the 0x30 bytes from the zip archive with 'UncompressMemory' ( I thought I create my own AddPack and UncompressPack using Compress/UncompressMemory - but as long as they don't compress/uncompress properly this isn't possible)
And finally the last problem - when you use windows to add the input file to a zip archive the file cannot be uncompressed with purebasic - the 'UncompressPackFile' fails for no special reason. (just create a ZIP file from the input file and remove the comment in the example).
Here's an example that can be used to demonstrate the problems:
Code: Select all
EnableExplicit
UseZipPacker()
Define iFileHdl.i
Define iPackHdl.i
Define sBaseDir.s
Define sSourceFile.s
Define sDestinationFile.s
Define sZipFile.s
Define sCompFile.s
Define sWindowsZipFile.s
Define *SourceMem
Define *CompressedMem
Define iCompressedSize.i
Define iUncompressedSize.i
sBaseDir=GetTemporaryDirectory()
sSourceFile=sBaseDir+"PbZipTest-InputFile.txt"
sZipFile=sBaseDir+"PbZipTest-ZipFile.zip"
sCompFile=sBaseDir+"PbZipTest-CompressFile.dat"
; sWindowsZipFile=sBasedir+GetFilePart(sSourceFile, #PB_FileSystem_NoExtension)+".zip"
sDestinationFile=sBaseDir+"UncompressedFromWindowsZip.txt"
;- Create TestFile
iFileHdl=CreateFile(#PB_Any, sSourceFile)
If iFileHdl
WriteStringN(iFileHdl, "0123456789")
WriteString(iFileHdl, "0123456789")
CloseFile(iFileHdl)
Debug "SourceFile >"+sSourceFile+"<"
Else
Debug "Error creating file!"
End
EndIf
;- add Testfile to new Zipfile
iPackHdl=CreatePack(#PB_Any, sZipFile)
If iPackHdl
If Not AddPackFile(iPackHdl, sSourceFile, GetFilePart(sSourceFile))
Debug "Error adding file to zip file!"
End
EndIf
ClosePack(iPackHdl)
Debug "ZipFile >"+sZipFile+"<"
Else
Debug "Error creating zip file! >"+sZipFile+"<"
End
EndIf
;- create 'Compressed' file from SourceFile
iFileHdl=ReadFile(#PB_Any, sSourceFile)
If Not iFileHdl
Debug "Error reading file!"
End
EndIf
*SourceMem=AllocateMemory(Lof(iFileHdl))
*CompressedMem=AllocateMemory(Lof(iFileHdl))
If Not *SourceMem Or Not *CompressedMem
Debug "error alloc mem!"
End
EndIf
If Not ReadData(iFileHdl, *SourceMem, MemorySize(*SourceMem))
Debug "Error reading file!"
End
EndIf
CloseFile(iFileHdl)
iCompressedSize=CompressMemory(*SourceMem, MemorySize(*SourceMem), *CompressedMem, MemorySize(*CompressedMem))
If iCompressedSize<=0
Debug "error compressing memory! >"+iCompressedSize+"<"
End
EndIf
Debug "CompressedSize >"+iCompressedSize+"< HEX >"+RSet(Hex(iCompressedSize), 4, "0")+"<"
iFileHdl=CreateFile(#PB_Any, sCompFile)
If Not iFileHdl
Debug "Error creating file!"
End
EndIf
If Not WriteData(iFileHdl, *CompressedMem, iCompressedSize)
Debug "Error writing data file!"
End
EndIf
CloseFile(iFileHdl)
Debug "File with compressed data >"+sCompFile+"<"
;- try to uncompress 'windows' compressed zip file
If sWindowsZipFile<>""
iPackHdl=OpenPack(#PB_Any, sWindowsZipFile)
If iPackHdl
iUncompressedSize=UncompressPackFile(iPackHdl, sDestinationFile, GetFilePart(sSourceFile))
If iUncompressedSize<=0
Debug "Error uncompressing file from windows zip file! >"+iUncompressedSize+"< >"+sWindowsZipFile+"<"
End
EndIf
ClosePack(iPackHdl)
Debug "Destination File >"+sDestinationFile+"<"
Else
Debug "Error opening windows zip file! >"+sWindowsZipFile+"<"
End
EndIf
EndIf