Skip to content

Commit

Permalink
Merge pull request #306 from weichsel/bugfix/uncontainedSymlinks
Browse files Browse the repository at this point in the history
Check Symlink Containment
  • Loading branch information
weichsel authored Dec 31, 2023
2 parents de38ebc + 35d31a1 commit cbd9900
Show file tree
Hide file tree
Showing 38 changed files with 81 additions and 44 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2017-2023 Thomas Zoechling (https://www.peakstep.com)
Copyright (c) 2017-2024 Thomas Zoechling (https://www.peakstep.com)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
2 changes: 1 addition & 1 deletion Sources/ZIPFoundation/Archive+BackingConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Archive+BackingConfiguration.swift
// ZIPFoundation
//
// Copyright © 2017-2023 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Copyright © 2017-2024 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Released under the MIT License.
//
// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information.
Expand Down
2 changes: 1 addition & 1 deletion Sources/ZIPFoundation/Archive+Helpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Archive+Helpers.swift
// ZIPFoundation
//
// Copyright © 2017-2023 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Copyright © 2017-2024 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Released under the MIT License.
//
// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information.
Expand Down
2 changes: 1 addition & 1 deletion Sources/ZIPFoundation/Archive+MemoryFile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Archive+MemoryFile.swift
// ZIPFoundation
//
// Copyright © 2017-2023 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Copyright © 2017-2024 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Released under the MIT License.
//
// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information.
Expand Down
2 changes: 1 addition & 1 deletion Sources/ZIPFoundation/Archive+Progress.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Archive+Progress.swift
// ZIPFoundation
//
// Copyright © 2017-2023 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Copyright © 2017-2024 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Released under the MIT License.
//
// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information.
Expand Down
17 changes: 13 additions & 4 deletions Sources/ZIPFoundation/Archive+Reading.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Archive+Reading.swift
// ZIPFoundation
//
// Copyright © 2017-2023 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Copyright © 2017-2024 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Released under the MIT License.
//
// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information.
Expand All @@ -18,10 +18,12 @@ extension Archive {
/// - url: The destination file URL.
/// - bufferSize: The maximum size of the read buffer and the decompression buffer (if needed).
/// - skipCRC32: Optional flag to skip calculation of the CRC32 checksum to improve performance.
/// - allowUncontainedSymlinks: Optional flag to allow symlinks that point to paths outside the destination.
/// - progress: A progress object that can be used to track or cancel the extract operation.
/// - Returns: The checksum of the processed content or 0 if the `skipCRC32` flag was set to `true`.
/// - Throws: An error if the destination file cannot be written or the entry contains malformed content.
public func extract(_ entry: Entry, to url: URL, bufferSize: Int = defaultReadChunkSize, skipCRC32: Bool = false,
public func extract(_ entry: Entry, to url: URL, bufferSize: Int = defaultReadChunkSize,
skipCRC32: Bool = false, allowUncontainedSymlinks: Bool = false,
progress: Progress? = nil) throws -> CRC32 {
guard bufferSize > 0 else {
throw ArchiveError.invalidBufferSize
Expand All @@ -30,7 +32,7 @@ extension Archive {
var checksum = CRC32(0)
switch entry.type {
case .file:
guard !fileManager.itemExists(at: url) else {
guard fileManager.itemExists(at: url) == false else {
throw CocoaError(.fileWriteFileExists, userInfo: [NSFilePathErrorKey: url.path])
}
try fileManager.createParentDirectoryStructure(for: url)
Expand All @@ -49,11 +51,18 @@ extension Archive {
checksum = try self.extract(entry, bufferSize: bufferSize, skipCRC32: skipCRC32,
progress: progress, consumer: consumer)
case .symlink:
guard !fileManager.itemExists(at: url) else {
guard fileManager.itemExists(at: url) == false else {
throw CocoaError(.fileWriteFileExists, userInfo: [NSFilePathErrorKey: url.path])
}
let consumer = { (data: Data) in
guard let linkPath = String(data: data, encoding: .utf8) else { throw ArchiveError.invalidEntryPath }

let parentURL = url.deletingLastPathComponent()
let isAbsolutePath = (linkPath as NSString).isAbsolutePath
let linkURL = URL(fileURLWithPath: linkPath, relativeTo: isAbsolutePath ? nil : parentURL)
let isContained = allowUncontainedSymlinks || linkURL.isContained(in: parentURL)
guard isContained else { throw ArchiveError.uncontainedSymlink }

try fileManager.createParentDirectoryStructure(for: url)
try fileManager.createSymbolicLink(atPath: url.path, withDestinationPath: linkPath)
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/ZIPFoundation/Archive+ReadingDeprecated.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Archive+ReadingDeprecated.swift
// ZIPFoundation
//
// Copyright © 2017-2023 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Copyright © 2017-2024 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Released under the MIT License.
//
// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information.
Expand Down
2 changes: 1 addition & 1 deletion Sources/ZIPFoundation/Archive+Writing.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Archive+Writing.swift
// ZIPFoundation
//
// Copyright © 2017-2023 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Copyright © 2017-2024 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Released under the MIT License.
//
// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information.
Expand Down
2 changes: 1 addition & 1 deletion Sources/ZIPFoundation/Archive+WritingDeprecated.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Archive+WritingDeprecated.swift
// ZIPFoundation
//
// Copyright © 2017-2023 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Copyright © 2017-2024 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Released under the MIT License.
//
// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information.
Expand Down
2 changes: 1 addition & 1 deletion Sources/ZIPFoundation/Archive+ZIP64.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Archive+ZIP64.swift
// ZIPFoundation
//
// Copyright © 2017-2023 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Copyright © 2017-2024 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Released under the MIT License.
//
// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information.
Expand Down
4 changes: 3 additions & 1 deletion Sources/ZIPFoundation/Archive.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Archive.swift
// ZIPFoundation
//
// Copyright © 2017-2023 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Copyright © 2017-2024 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Released under the MIT License.
//
// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information.
Expand Down Expand Up @@ -90,6 +90,8 @@ public final class Archive: Sequence {
case invalidCentralDirectoryEntryCount
/// Thrown when an archive does not contain the required End of Central Directory Record.
case missingEndOfCentralDirectoryRecord
/// Thrown when an entry contains a symlink pointing to a path outside the destination directory.
case uncontainedSymlink
}

/// The access mode for an `Archive`.
Expand Down
2 changes: 1 addition & 1 deletion Sources/ZIPFoundation/Data+Compression.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Data+Compression.swift
// ZIPFoundation
//
// Copyright © 2017-2023 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Copyright © 2017-2024 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Released under the MIT License.
//
// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information.
Expand Down
2 changes: 1 addition & 1 deletion Sources/ZIPFoundation/Data+CompressionDeprecated.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Data+CompressionDeprecated.swift
// ZIPFoundation
//
// Copyright © 2017-2023 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Copyright © 2017-2024 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Released under the MIT License.
//
// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information.
Expand Down
2 changes: 1 addition & 1 deletion Sources/ZIPFoundation/Data+Serialization.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Data+Serialization.swift
// ZIPFoundation
//
// Copyright © 2017-2023 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Copyright © 2017-2024 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Released under the MIT License.
//
// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information.
Expand Down
2 changes: 1 addition & 1 deletion Sources/ZIPFoundation/Entry+Serialization.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Entry+Serialization.swift
// ZIPFoundation
//
// Copyright © 2017-2023 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Copyright © 2017-2024 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Released under the MIT License.
//
// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information.
Expand Down
2 changes: 1 addition & 1 deletion Sources/ZIPFoundation/Entry+ZIP64.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Entry+ZIP64.swift
// ZIPFoundation
//
// Copyright © 2017-2023 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Copyright © 2017-2024 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Released under the MIT License.
//
// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information.
Expand Down
2 changes: 1 addition & 1 deletion Sources/ZIPFoundation/Entry.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Entry.swift
// ZIPFoundation
//
// Copyright © 2017-2023 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Copyright © 2017-2024 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Released under the MIT License.
//
// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information.
Expand Down
13 changes: 9 additions & 4 deletions Sources/ZIPFoundation/FileManager+ZIP.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// FileManager+ZIP.swift
// ZIPFoundation
//
// Copyright © 2017-2023 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Copyright © 2017-2024 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Released under the MIT License.
//
// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information.
Expand Down Expand Up @@ -87,10 +87,12 @@ extension FileManager {
/// - sourceURL: The file URL pointing to an existing ZIP file.
/// - destinationURL: The file URL that identifies the destination directory of the unzip operation.
/// - skipCRC32: Optional flag to skip calculation of the CRC32 checksum to improve performance.
/// - allowUncontainedSymlinks: Optional flag to allow symlinks that point to paths outside the destination.
/// - progress: A progress object that can be used to track or cancel the unzip operation.
/// - pathEncoding: Encoding for entry paths. Overrides the encoding specified in the archive.
/// - Throws: Throws an error if the source item does not exist or the destination URL is not writable.
public func unzipItem(at sourceURL: URL, to destinationURL: URL, skipCRC32: Bool = false,
public func unzipItem(at sourceURL: URL, to destinationURL: URL,
skipCRC32: Bool = false, allowUncontainedSymlinks: Bool = false,
progress: Progress? = nil, pathEncoding: String.Encoding? = nil) throws {
let fileManager = FileManager()
guard fileManager.itemExists(at: sourceURL) else {
Expand All @@ -114,9 +116,12 @@ extension FileManager {
if let progress = progress {
let entryProgress = archive.makeProgressForReading(entry)
progress.addChild(entryProgress, withPendingUnitCount: entryProgress.totalUnitCount)
crc32 = try archive.extract(entry, to: entryURL, skipCRC32: skipCRC32, progress: entryProgress)
crc32 = try archive.extract(entry, to: entryURL,
skipCRC32: skipCRC32, allowUncontainedSymlinks: allowUncontainedSymlinks,
progress: entryProgress)
} else {
crc32 = try archive.extract(entry, to: entryURL, skipCRC32: skipCRC32)
crc32 = try archive.extract(entry, to: entryURL,
skipCRC32: skipCRC32, allowUncontainedSymlinks: allowUncontainedSymlinks)
}

func verifyChecksumIfNecessary() throws {
Expand Down
2 changes: 1 addition & 1 deletion Sources/ZIPFoundation/URL+ZIP.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// URL+ZIP.swift
// ZIPFoundation
//
// Copyright © 2017-2023 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Copyright © 2017-2024 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Released under the MIT License.
//
// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information.
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// ZIPFoundationArchiveTests+ZIP64.swift
// ZIPFoundation
//
// Copyright © 2017-2023 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Copyright © 2017-2024 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Released under the MIT License.
//
// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information.
Expand Down
2 changes: 1 addition & 1 deletion Tests/ZIPFoundationTests/ZIPFoundationArchiveTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// ZIPFoundationErrorConditionTests.swift
// ZIPFoundation
//
// Copyright © 2017-2023 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Copyright © 2017-2024 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Released under the MIT License.
//
// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// ZIPFoundationDataSerializationTests.swift
// ZIPFoundation
//
// Copyright © 2017-2023 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Copyright © 2017-2024 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Released under the MIT License.
//
// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// ZIPFoundationEntryTests+ZIP64.swift
// ZIPFoundation
//
// Copyright © 2017-2023 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Copyright © 2017-2024 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Released under the MIT License.
//
// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information.
Expand Down
2 changes: 1 addition & 1 deletion Tests/ZIPFoundationTests/ZIPFoundationEntryTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// ZIPFoundationEntryTests.swift
// ZIPFoundation
//
// Copyright © 2017-2023 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Copyright © 2017-2024 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Released under the MIT License.
//
// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// ZIPFoundationErrorConditionTests+ZIP64.swift
// ZIPFoundation
//
// Copyright © 2017-2023 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Copyright © 2017-2024 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Released under the MIT License.
//
// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// ZIPFoundationErrorConditionTests.swift
// ZIPFoundation
//
// Copyright © 2017-2023 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Copyright © 2017-2024 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Released under the MIT License.
//
// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// ZIPFoundationFileAttributeTests.swift
// ZIPFoundation
//
// Copyright © 2017-2023 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Copyright © 2017-2024 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Released under the MIT License.
//
// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// ZIPFoundationFileManagerTests+ZIP64.swift
// ZIPFoundation
//
// Copyright © 2017-2023 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Copyright © 2017-2024 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Released under the MIT License.
//
// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information.
Expand Down
24 changes: 22 additions & 2 deletions Tests/ZIPFoundationTests/ZIPFoundationFileManagerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// ZIPFoundationFileManagerTests.swift
// ZIPFoundation
//
// Copyright © 2017-2023 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Copyright © 2017-2024 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Released under the MIT License.
//
// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information.
Expand Down Expand Up @@ -97,7 +97,7 @@ extension ZIPFoundationTests {
for entry in archive {
let directoryURL = destinationURL.appendingPathComponent(entry.path)
itemsExist = fileManager.itemExists(at: directoryURL)
if !itemsExist { break }
if itemsExist == false { break }
}
XCTAssert(itemsExist)
}
Expand Down Expand Up @@ -142,6 +142,26 @@ extension ZIPFoundationTests {
throws: Archive.ArchiveError.missingEndOfCentralDirectoryRecord)
}

func testUnzipUncontainedSymlink() throws {
let fileManager = FileManager()
let archive = self.archive(for: #function, mode: .read)
let destinationURL = self.createDirectory(for: #function)
XCTAssertSwiftError(try fileManager.unzipItem(at: archive.url, to: destinationURL),
throws: Archive.ArchiveError.uncontainedSymlink)

var linkArchiveURL = ZIPFoundationTests.tempZipDirectoryURL
linkArchiveURL.appendPathComponent(self.archiveName(for: #function))
let linkURL = linkArchiveURL.deletingLastPathComponent()
let linkTarget = linkURL.path
let linkArchive = try XCTUnwrap(try? Archive(url: linkArchiveURL, accessMode: .create))
try? linkArchive.addEntry(with: "link", type: .symlink, uncompressedSize: Int64(4),
provider: { (_, _) -> Data in
return linkTarget.data(using: .utf8) ?? Data()
})
try? fileManager.unzipItem(at: linkArchiveURL, to: destinationURL, allowUncontainedSymlinks: true)
XCTAssert(fileManager.itemExists(at: destinationURL.appendingPathComponent("link")))
}

// On Darwin platforms, we want the same behavior as the system-provided ZIP utilities.
// On the Mac, this includes the graphical Archive Utility as well as the `ditto`
// command line tool.
Expand Down
2 changes: 1 addition & 1 deletion Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// ZIPFoundationMemoryTests.swift
// ZIPFoundation
//
// Copyright © 2017-2023 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Copyright © 2017-2024 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
// Released under the MIT License.
//
// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information.
Expand Down
Loading

0 comments on commit cbd9900

Please sign in to comment.