Skip to content

Commit

Permalink
Add initial support for deflate64 zip files
Browse files Browse the repository at this point in the history
  • Loading branch information
iffy committed Aug 6, 2024
1 parent 687f03f commit 05d584f
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 7 deletions.
8 changes: 5 additions & 3 deletions src/zippy/internal.nim
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const allowSimd* =
const
maxCodeLength* = 15
maxLitLenCodes* = 286
maxDistanceCodes* = 30
maxDistanceCodes* = 32
maxFixedLitLenCodes* = 288
maxWindowSize* = 32768
maxUncompressedBlockSize* = 65535
Expand Down Expand Up @@ -86,7 +86,8 @@ const
2049, 3073, # 22-23
4097, 6145, # 24-25
8193, 12289, # 26-27
16385, 24577 # 28-29
16385, 24577, # 28-29
32769, 49153, # 30-31
]

baseDistanceExtraBits* = [
Expand All @@ -103,7 +104,8 @@ const
10, 10, # 22-23
11, 11, # 24-25
12, 12, # 26-27
13, 13 # 28-29
13, 13, # 28-29
14, 14, # 30-31
]

clclOrder* = [
Expand Down
9 changes: 6 additions & 3 deletions src/zippy/ziparchives.nim
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ const
zip64EndOfCentralDirectorySignature = 0x06064b50.uint32
zip64EndOfCentralDirectoryLocatorSignature = 0x07064b50.uint32
zip64ExtraFieldId = 1.uint16
NoneCompression = 0.uint16
DeflateCompression = 8.uint16
Deflate64Compression = 9.uint16

type
ZipArchiveRecordKind = enum
Expand Down Expand Up @@ -78,11 +81,11 @@ proc extractFile*(

case record.kind:
of FileRecord:
if compressionMethod == 0: # No compression
if compressionMethod == NoneCompression: # No compression
if record.compressedSize > 0:
result.setLen(record.compressedSize)
copyMem(result[0].addr, src[pos].addr, record.compressedSize)
elif compressionMethod == 8: # Deflate
elif compressionMethod in [DeflateCompression, Deflate64Compression]:
result = uncompress(src[pos].addr, record.compressedSize, dfDeflate)
else:
raise newException(ZippyError, "Unsupported archive, compression method")
Expand Down Expand Up @@ -293,7 +296,7 @@ proc openZipArchive*(
# internalFileAttr = read16(src, pos + 36)
externalFileAttr = read32(src, pos + 38)

if compressionMethod notin [0.uint16, 8]:
if compressionMethod notin [NoneCompression, DeflateCompression, Deflate64Compression]:
raise newException(ZippyError, "Unsupported archive, compression method")

if fileDiskNumber != 0:
Expand Down
Binary file added tests/data/ziparchives/deflate64test.zip
Binary file not shown.
24 changes: 23 additions & 1 deletion tests/test_ziparchives_read.nim
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import std/os, zippy/ziparchives, std/tables
import std/os, zippy/ziparchives, std/tables, std/strutils, std/strformat

const testDir = getTempDir() # "tmp/zip"

Expand Down Expand Up @@ -61,3 +61,25 @@ block:
except:
let e = getCurrentException()
doAssert e.msg == "Error adding file tests/data/ziparchives/ to archive, appears to be a directory?"

block: # Test deflate64
# test file obtained from https://github.com/brianhelba/zipfile-deflate64/tree/beec33184da6da4697a1994c0ac4c64cef8cff50/tests/data
let
archive = openZipArchive("tests/data/ziparchives/deflate64test.zip")
entries = {
"100_lines.txt": (101, 1890),
"100k_lines.txt": (100_001, 2188890),
"10_lines.txt": (11, 180),
"10k_lines.txt": (10_001, 208890),
}.toTable()
var numEntries: int
for entry in archive.walkFiles:
let
contents = archive.extractFile(entry)
actual_lines = contents.splitLines.len
actual_size = contents.len
(lines, size) = entries[entry]
doAssert actual_lines == lines, &"Expected {entry} to have {lines} not {actual_lines}"
doAssert actual_size == size, &"Expected {entry} to be {size} bytes not {actual_size}"
inc numEntries
doAssert numEntries == entries.len

0 comments on commit 05d584f

Please sign in to comment.