Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix unzip bug #7

Merged
merged 2 commits into from
Aug 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 12 additions & 11 deletions Sources/Zip/Zip.swift
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ public class Zip {
}

let fullPath = destination.appendingPathComponent(pathString).standardized.path
// `.standardized` removes any ".. to move a level up".
// If we then check that the `fullPath` starts with the destination directory we know we are not extracting "outside" te destination.
// `.standardized` removes any `..` to move a level up.
// If we then check that the `fullPath` starts with the destination directory we know we are not extracting "outside" the destination.
guard fullPath.starts(with: destination.standardized.path) else {
throw ZipError.unzipFail
}
Expand Down Expand Up @@ -146,17 +146,18 @@ public class Zip {
}

var writeBytes: UInt64 = 0
while let filePointer = fopen(fullPath, "wb") {
defer { fclose(filePointer) }
let filePointer: UnsafeMutablePointer<FILE>? = fopen(fullPath, "wb")
while let filePointer {
let readBytes = unzReadCurrentFile(zip, &buffer, bufferSize)
if readBytes > 0 {
guard fwrite(buffer, Int(readBytes), 1, filePointer) == 1 else {
throw ZipError.unzipFail
}
writeBytes += UInt64(readBytes)
} else { break }
guard readBytes > 0 else { break }
guard fwrite(buffer, Int(readBytes), 1, filePointer) == 1 else {
throw ZipError.unzipFail
}
writeBytes += UInt64(readBytes)
}

if let filePointer { fclose(filePointer) }

crc_ret = unzCloseCurrentFile(zip)
if crc_ret == UNZ_CRCERROR {
throw ZipError.unzipFail
Expand All @@ -182,7 +183,7 @@ public class Zip {

// Update progress handler
if let progressHandler = progress {
progressHandler((currentPosition/totalSize))
progressHandler((currentPosition / totalSize))
}

if let fileHandler = fileOutputHandler,
Expand Down
17 changes: 14 additions & 3 deletions Tests/ZipTests/ZipTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ final class ZipTests: XCTestCase {
try? FileManager.default.removeItem(at: destinationURL)
}
XCTAssertTrue(FileManager.default.fileExists(atPath: destinationURL.path))
try XCTAssertGreaterThan(Data(contentsOf: destinationURL.appendingPathComponent("3crBXeO.gif")).count, 0)
try XCTAssertGreaterThan(Data(contentsOf: destinationURL.appendingPathComponent("kYkLkPf.gif")).count, 0)
}

func testQuickUnzipNonExistingPath() {
Expand All @@ -59,12 +61,15 @@ final class ZipTests: XCTestCase {

func testQuickUnzipProgress() throws {
let filePath = url(forResource: "bb8", withExtension: "zip")!
let destinationURL = try Zip.quickUnzipFile(filePath, progress: { progress in
let destinationURL = try Zip.quickUnzipFile(filePath) { progress in
XCTAssertFalse(progress.isNaN)
})
}
addTeardownBlock {
try? FileManager.default.removeItem(at: destinationURL)
}
XCTAssertTrue(FileManager.default.fileExists(atPath: destinationURL.path))
try XCTAssertGreaterThan(Data(contentsOf: destinationURL.appendingPathComponent("3crBXeO.gif")).count, 0)
try XCTAssertGreaterThan(Data(contentsOf: destinationURL.appendingPathComponent("kYkLkPf.gif")).count, 0)
}

func testQuickUnzipOnlineURL() {
Expand All @@ -79,6 +84,8 @@ final class ZipTests: XCTestCase {
XCTAssertNoThrow(try Zip.unzipFile(filePath, destination: destinationPath, overwrite: true, password: "password", progress: nil))

XCTAssertTrue(FileManager.default.fileExists(atPath: destinationPath.path))
try XCTAssertGreaterThan(Data(contentsOf: destinationPath.appendingPathComponent("3crBXeO.gif")).count, 0)
try XCTAssertGreaterThan(Data(contentsOf: destinationPath.appendingPathComponent("kYkLkPf.gif")).count, 0)
}

func testImplicitProgressUnzip() throws {
Expand Down Expand Up @@ -113,7 +120,8 @@ final class ZipTests: XCTestCase {
let imageURL1 = url(forResource: "3crBXeO", withExtension: "gif")!
let imageURL2 = url(forResource: "kYkLkPf", withExtension: "gif")!
let destinationURL = try Zip.quickZipFiles([imageURL1, imageURL2], fileName: "archive")
XCTAssertTrue(FileManager.default.fileExists(atPath:destinationURL.path))
XCTAssertTrue(FileManager.default.fileExists(atPath: destinationURL.path))
try XCTAssertGreaterThan(Data(contentsOf: destinationURL).count, 0)
addTeardownBlock {
try? FileManager.default.removeItem(at: destinationURL)
}
Expand All @@ -126,6 +134,7 @@ final class ZipTests: XCTestCase {
XCTAssertFalse(progress.isNaN)
}
XCTAssertTrue(FileManager.default.fileExists(atPath:destinationURL.path))
try XCTAssertGreaterThan(Data(contentsOf: destinationURL).count, 0)
addTeardownBlock {
try? FileManager.default.removeItem(at: destinationURL)
}
Expand Down Expand Up @@ -337,6 +346,7 @@ final class ZipTests: XCTestCase {
XCTAssert(FileManager.default.fileExists(atPath: destinationFolder.appendingPathComponent("metadata.json").path))
XCTAssert(FileManager.default.fileExists(atPath: destinationFolder.appendingPathComponent("main/index.html").path))
XCTAssert(FileManager.default.fileExists(atPath: destinationFolder.appendingPathComponent("main/index/index.json").path))
try XCTAssertGreaterThan(Data(contentsOf: destinationFolder.appendingPathComponent("metadata.json")).count, 0)

let unzippedFiles = try FileManager.default.contentsOfDirectory(atPath: destinationFolder.path)

Expand All @@ -350,6 +360,7 @@ final class ZipTests: XCTestCase {
XCTAssert(FileManager.default.fileExists(atPath: newDestinationFolder.appendingPathComponent("metadata.json").path))
XCTAssert(FileManager.default.fileExists(atPath: newDestinationFolder.appendingPathComponent("main/index.html").path))
XCTAssert(FileManager.default.fileExists(atPath: newDestinationFolder.appendingPathComponent("main/index/index.json").path))
try XCTAssertGreaterThan(Data(contentsOf: newDestinationFolder.appendingPathComponent("metadata.json")).count, 0)

let newUnzippedFiles = try FileManager.default.contentsOfDirectory(atPath: newDestinationFolder.path)
XCTAssertEqual(unzippedFiles, newUnzippedFiles)
Expand Down