mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-15 13:35:19 +00:00
Switch zip implementation
This commit is contained in:
parent
b61e28ae44
commit
f29cfa3f24
@ -15,7 +15,7 @@ swift_library(
|
||||
"//submodules/SyncCore:SyncCore",
|
||||
"//submodules/TelegramCore:TelegramCore",
|
||||
"//submodules/AppBundle:AppBundle",
|
||||
"//third-party/ZIPFoundation:ZIPFoundation",
|
||||
"//third-party/ZipArchive:ZipArchive",
|
||||
"//submodules/AccountContext:AccountContext",
|
||||
"//submodules/PresentationDataUtils:PresentationDataUtils",
|
||||
"//submodules/RadialStatusNode:RadialStatusNode",
|
||||
|
@ -11,7 +11,7 @@ import PresentationDataUtils
|
||||
import RadialStatusNode
|
||||
import AnimatedStickerNode
|
||||
import AppBundle
|
||||
import ZIPFoundation
|
||||
import ZipArchive
|
||||
import MimeTypes
|
||||
import ConfettiEffect
|
||||
import TelegramUniversalVideoContent
|
||||
@ -398,10 +398,10 @@ public final class ChatImportActivityScreen: ViewController {
|
||||
private var presentationData: PresentationData
|
||||
fileprivate let cancel: () -> Void
|
||||
fileprivate var peerId: PeerId
|
||||
private let archive: Archive
|
||||
private let archivePath: String
|
||||
private let mainEntry: TempBoxFile
|
||||
private let mainEntrySize: Int
|
||||
private let otherEntries: [(Entry, String, ChatHistoryImport.MediaType, Promise<TempBoxFile?>)]
|
||||
private let otherEntries: [(SSZipEntry, String, ChatHistoryImport.MediaType, Promise<TempBoxFile?>)]
|
||||
private let totalBytes: Int
|
||||
|
||||
private var pendingEntries: [String: (Int, Float)] = [:]
|
||||
@ -415,27 +415,27 @@ public final class ChatImportActivityScreen: ViewController {
|
||||
}
|
||||
}
|
||||
|
||||
public init(context: AccountContext, cancel: @escaping () -> Void, peerId: PeerId, archive: Archive, mainEntry: TempBoxFile, otherEntries: [(Entry, String, ChatHistoryImport.MediaType)]) {
|
||||
public init(context: AccountContext, cancel: @escaping () -> Void, peerId: PeerId, archivePath: String, mainEntry: TempBoxFile, otherEntries: [(SSZipEntry, String, ChatHistoryImport.MediaType)]) {
|
||||
self.context = context
|
||||
self.cancel = cancel
|
||||
self.peerId = peerId
|
||||
self.archive = archive
|
||||
self.archivePath = archivePath
|
||||
self.mainEntry = mainEntry
|
||||
|
||||
self.otherEntries = otherEntries.map { entry -> (Entry, String, ChatHistoryImport.MediaType, Promise<TempBoxFile?>) in
|
||||
self.otherEntries = otherEntries.map { entry -> (SSZipEntry, String, ChatHistoryImport.MediaType, Promise<TempBoxFile?>) in
|
||||
let signal = Signal<TempBoxFile?, NoError> { subscriber in
|
||||
let tempFile = TempBox.shared.tempFile(fileName: entry.1)
|
||||
do {
|
||||
let _ = try archive.extract(entry.0, to: URL(fileURLWithPath: tempFile.path))
|
||||
if SSZipArchive.extractFileFromArchive(atPath: archivePath, filePath: entry.0.path, toPath: tempFile.path) {
|
||||
subscriber.putNext(tempFile)
|
||||
subscriber.putCompletion()
|
||||
} catch {
|
||||
} else {
|
||||
subscriber.putNext(nil)
|
||||
subscriber.putCompletion()
|
||||
}
|
||||
|
||||
return EmptyDisposable
|
||||
}
|
||||
|> runOn(Queue.concurrentDefaultQueue())
|
||||
let promise = Promise<TempBoxFile?>()
|
||||
promise.set(signal)
|
||||
return (entry.0, entry.1, entry.2, promise)
|
||||
@ -448,12 +448,12 @@ public final class ChatImportActivityScreen: ViewController {
|
||||
}
|
||||
|
||||
for (entry, fileName, _) in otherEntries {
|
||||
self.pendingEntries[fileName] = (entry.uncompressedSize, 0.0)
|
||||
self.pendingEntries[fileName] = (Int(entry.uncompressedSize), 0.0)
|
||||
}
|
||||
|
||||
var totalBytes: Int = self.mainEntrySize
|
||||
for entry in self.otherEntries {
|
||||
totalBytes += entry.0.uncompressedSize
|
||||
totalBytes += Int(entry.0.uncompressedSize)
|
||||
}
|
||||
self.totalBytes = totalBytes
|
||||
|
||||
@ -512,7 +512,6 @@ public final class ChatImportActivityScreen: ViewController {
|
||||
self.controllerNode.updateState(state: .progress(0.0), animated: true)
|
||||
|
||||
let context = self.context
|
||||
let archive = self.archive
|
||||
let mainEntry = self.mainEntry
|
||||
let otherEntries = self.otherEntries
|
||||
|
||||
@ -550,6 +549,7 @@ public final class ChatImportActivityScreen: ViewController {
|
||||
for (_, fileName, mediaType, fileData) in otherEntries {
|
||||
let unpackedFile: Signal<TempBoxFile, ImportError> = fileData.get()
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue
|
||||
|> castError(ImportError.self)
|
||||
|> mapToSignal { file -> Signal<TempBoxFile, ImportError> in
|
||||
if let file = file {
|
||||
|
@ -213,7 +213,7 @@ swift_library(
|
||||
"//submodules/AnimatedNavigationStripeNode:AnimatedNavigationStripeNode",
|
||||
"//submodules/AudioBlob:AudioBlob",
|
||||
"//Telegram:GeneratedSources",
|
||||
"//third-party/ZIPFoundation:ZIPFoundation",
|
||||
"//third-party/ZipArchive:ZipArchive",
|
||||
"//submodules/ChatImportUI:ChatImportUI",
|
||||
"//submodules/ChatHistoryImportTasks:ChatHistoryImportTasks",
|
||||
"//submodules/DatePickerNode:DatePickerNode",
|
||||
|
@ -21,7 +21,7 @@ import MobileCoreServices
|
||||
import OverlayStatusController
|
||||
import PresentationDataUtils
|
||||
import ChatImportUI
|
||||
import ZIPFoundation
|
||||
import ZipArchive
|
||||
import ActivityIndicator
|
||||
|
||||
private let inForeground = ValuePromise<Bool>(false, ignoreRepeated: true)
|
||||
@ -392,7 +392,7 @@ public class ShareRootControllerImpl {
|
||||
if attachment.hasItemConformingToTypeIdentifier(kUTTypeFileURL as String) {
|
||||
attachment.loadItem(forTypeIdentifier: kUTTypeFileURL as String, completionHandler: { result, error in
|
||||
Queue.mainQueue().async {
|
||||
guard let url = result as? URL else {
|
||||
guard let url = result as? URL, url.isFileURL else {
|
||||
beginShare()
|
||||
return
|
||||
}
|
||||
@ -405,7 +405,10 @@ public class ShareRootControllerImpl {
|
||||
beginShare()
|
||||
return
|
||||
}
|
||||
guard let archive = Archive(url: url, accessMode: .read) else {
|
||||
|
||||
let archivePath = url.path
|
||||
|
||||
guard let entries = SSZipArchive.getEntriesForFile(atPath: archivePath) else {
|
||||
beginShare()
|
||||
return
|
||||
}
|
||||
@ -417,8 +420,8 @@ public class ShareRootControllerImpl {
|
||||
]
|
||||
|
||||
var maybeMainFileName: String?
|
||||
mainFileLoop: for entry in archive {
|
||||
let entryFileName = entry.path(using: .utf8).replacingOccurrences(of: "/", with: "_").replacingOccurrences(of: "..", with: "_")
|
||||
mainFileLoop: for entry in entries {
|
||||
let entryFileName = entry.path.replacingOccurrences(of: "/", with: "_").replacingOccurrences(of: "..", with: "_")
|
||||
let fullRange = NSRange(entryFileName.startIndex ..< entryFileName.endIndex, in: entryFileName)
|
||||
for expression in mainFileNames {
|
||||
if expression.firstMatch(in: entryFileName, options: [], range: fullRange) != nil {
|
||||
@ -438,19 +441,20 @@ public class ShareRootControllerImpl {
|
||||
let stickerRegex = try! NSRegularExpression(pattern: "[\\d]+-STICKER-.*?\\.webp")
|
||||
let voiceRegex = try! NSRegularExpression(pattern: "[\\d]+-AUDIO-.*?\\.opus")
|
||||
|
||||
var otherEntries: [(Entry, String, ChatHistoryImport.MediaType)] = []
|
||||
var otherEntries: [(SSZipEntry, String, ChatHistoryImport.MediaType)] = []
|
||||
|
||||
var mainFile: TempBoxFile?
|
||||
do {
|
||||
for entry in archive {
|
||||
let entryPath = entry.path(using: .utf8).replacingOccurrences(of: "/", with: "_").replacingOccurrences(of: "..", with: "_")
|
||||
for entry in entries {
|
||||
let entryPath = entry.path.replacingOccurrences(of: "/", with: "_").replacingOccurrences(of: "..", with: "_")
|
||||
if entryPath.isEmpty {
|
||||
continue
|
||||
}
|
||||
let tempFile = TempBox.shared.tempFile(fileName: entryPath)
|
||||
if entryPath == mainFileName {
|
||||
let _ = try archive.extract(entry, to: URL(fileURLWithPath: tempFile.path))
|
||||
mainFile = tempFile
|
||||
if SSZipArchive.extractFileFromArchive(atPath: archivePath, filePath: entry.path, toPath: tempFile.path) {
|
||||
mainFile = tempFile
|
||||
}
|
||||
} else {
|
||||
let entryFileName = (entryPath as NSString).lastPathComponent
|
||||
if !entryFileName.isEmpty {
|
||||
@ -557,7 +561,7 @@ public class ShareRootControllerImpl {
|
||||
navigationController.view.endEditing(true)
|
||||
navigationController.pushViewController(ChatImportActivityScreen(context: context, cancel: {
|
||||
self?.getExtensionContext()?.completeRequest(returningItems: nil, completionHandler: nil)
|
||||
}, peerId: peerId, archive: archive, mainEntry: mainFile, otherEntries: otherEntries))
|
||||
}, peerId: peerId, archivePath: archivePath, mainEntry: mainFile, otherEntries: otherEntries))
|
||||
}
|
||||
|
||||
attemptSelectionImpl = { peer in
|
||||
@ -671,7 +675,7 @@ public class ShareRootControllerImpl {
|
||||
navigationController.view.endEditing(true)
|
||||
navigationController.pushViewController(ChatImportActivityScreen(context: context, cancel: {
|
||||
self?.getExtensionContext()?.completeRequest(returningItems: nil, completionHandler: nil)
|
||||
}, peerId: peerId, archive: archive, mainEntry: mainFile, otherEntries: otherEntries))
|
||||
}, peerId: peerId, archivePath: archivePath, mainEntry: mainFile, otherEntries: otherEntries))
|
||||
}
|
||||
|
||||
attemptSelectionImpl = { [weak controller] peer in
|
||||
@ -733,7 +737,7 @@ public class ShareRootControllerImpl {
|
||||
navigationController.view.endEditing(true)
|
||||
navigationController.pushViewController(ChatImportActivityScreen(context: context, cancel: {
|
||||
self?.getExtensionContext()?.completeRequest(returningItems: nil, completionHandler: nil)
|
||||
}, peerId: peerId, archive: archive, mainEntry: mainFile, otherEntries: otherEntries))
|
||||
}, peerId: peerId, archivePath: archivePath, mainEntry: mainFile, otherEntries: otherEntries))
|
||||
}
|
||||
|
||||
attemptSelectionImpl = { [weak controller] peer in
|
||||
|
12
third-party/ZIPFoundation/BUILD
vendored
12
third-party/ZIPFoundation/BUILD
vendored
@ -1,12 +0,0 @@
|
||||
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
|
||||
|
||||
swift_library(
|
||||
name = "ZIPFoundation",
|
||||
module_name = "ZIPFoundation",
|
||||
srcs = glob([
|
||||
"Sources/**/*.swift",
|
||||
]),
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
],
|
||||
)
|
@ -1,178 +0,0 @@
|
||||
//
|
||||
// Archive+MemoryFile.swift
|
||||
// ZIPFoundation
|
||||
//
|
||||
// Copyright © 2017-2020 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
#if swift(>=5.0)
|
||||
|
||||
extension Archive {
|
||||
/// Returns a `Data` object containing a representation of the receiver.
|
||||
public var data: Data? { return memoryFile?.data }
|
||||
|
||||
static func configureMemoryBacking(for data: Data, mode: AccessMode)
|
||||
-> (UnsafeMutablePointer<FILE>, MemoryFile)? {
|
||||
let posixMode: String
|
||||
switch mode {
|
||||
case .read: posixMode = "rb"
|
||||
case .create: posixMode = "wb+"
|
||||
case .update: posixMode = "rb+"
|
||||
}
|
||||
let memoryFile = MemoryFile(data: data)
|
||||
guard let archiveFile = memoryFile.open(mode: posixMode) else { return nil }
|
||||
|
||||
if mode == .create {
|
||||
let endOfCentralDirectoryRecord = EndOfCentralDirectoryRecord(numberOfDisk: 0, numberOfDiskStart: 0,
|
||||
totalNumberOfEntriesOnDisk: 0,
|
||||
totalNumberOfEntriesInCentralDirectory: 0,
|
||||
sizeOfCentralDirectory: 0,
|
||||
offsetToStartOfCentralDirectory: 0,
|
||||
zipFileCommentLength: 0,
|
||||
zipFileCommentData: Data())
|
||||
_ = endOfCentralDirectoryRecord.data.withUnsafeBytes { (buffer: UnsafeRawBufferPointer) in
|
||||
fwrite(buffer.baseAddress, buffer.count, 1, archiveFile) // Errors handled during read
|
||||
}
|
||||
}
|
||||
return (archiveFile, memoryFile)
|
||||
}
|
||||
}
|
||||
|
||||
class MemoryFile {
|
||||
private(set) var data: Data
|
||||
private var offset = 0
|
||||
|
||||
init(data: Data = Data()) {
|
||||
self.data = data
|
||||
}
|
||||
|
||||
func open(mode: String) -> UnsafeMutablePointer<FILE>? {
|
||||
let cookie = Unmanaged.passRetained(self)
|
||||
let writable = mode.count > 0 && (mode.first! != "r" || mode.last! == "+")
|
||||
let append = mode.count > 0 && mode.first! == "a"
|
||||
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
|
||||
let result = writable
|
||||
? funopen(cookie.toOpaque(), readStub, writeStub, seekStub, closeStub)
|
||||
: funopen(cookie.toOpaque(), readStub, nil, seekStub, closeStub)
|
||||
#else
|
||||
let stubs = cookie_io_functions_t(read: readStub, write: writeStub, seek: seekStub, close: closeStub)
|
||||
let result = fopencookie(cookie.toOpaque(), mode, stubs)
|
||||
#endif
|
||||
if append {
|
||||
fseek(result, 0, SEEK_END)
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
private extension MemoryFile {
|
||||
func readData(buffer: UnsafeMutableRawBufferPointer) -> Int {
|
||||
let size = min(buffer.count, data.count-offset)
|
||||
let start = data.startIndex
|
||||
data.copyBytes(to: buffer.bindMemory(to: UInt8.self), from: start+offset..<start+offset+size)
|
||||
offset += size
|
||||
return size
|
||||
}
|
||||
|
||||
func writeData(buffer: UnsafeRawBufferPointer) -> Int {
|
||||
let start = data.startIndex
|
||||
if offset < data.count && offset+buffer.count > data.count {
|
||||
data.removeSubrange(start+offset..<start+data.count)
|
||||
} else if offset > data.count {
|
||||
data.append(Data(count: offset-data.count))
|
||||
}
|
||||
if offset == data.count {
|
||||
data.append(buffer.bindMemory(to: UInt8.self))
|
||||
} else {
|
||||
let start = data.startIndex // May have changed in earlier mutation
|
||||
data.replaceSubrange(start+offset..<start+offset+buffer.count, with: buffer.bindMemory(to: UInt8.self))
|
||||
}
|
||||
offset += buffer.count
|
||||
return buffer.count
|
||||
}
|
||||
|
||||
func seek(offset: Int, whence: Int32) -> Int {
|
||||
var result = -1
|
||||
if whence == SEEK_SET {
|
||||
result = offset
|
||||
} else if whence == SEEK_CUR {
|
||||
result = self.offset + offset
|
||||
} else if whence == SEEK_END {
|
||||
result = data.count + offset
|
||||
}
|
||||
self.offset = result
|
||||
return self.offset
|
||||
}
|
||||
}
|
||||
|
||||
private func fileFromCookie(cookie: UnsafeRawPointer) -> MemoryFile {
|
||||
return Unmanaged<MemoryFile>.fromOpaque(cookie).takeUnretainedValue()
|
||||
}
|
||||
|
||||
private func closeStub(_ cookie: UnsafeMutableRawPointer?) -> Int32 {
|
||||
if let cookie = cookie {
|
||||
Unmanaged<MemoryFile>.fromOpaque(cookie).release()
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
|
||||
private func readStub(_ cookie: UnsafeMutableRawPointer?,
|
||||
_ bytePtr: UnsafeMutablePointer<Int8>?,
|
||||
_ count: Int32) -> Int32 {
|
||||
guard let cookie = cookie, let bytePtr = bytePtr else { return 0 }
|
||||
return Int32(fileFromCookie(cookie: cookie).readData(
|
||||
buffer: UnsafeMutableRawBufferPointer(start: bytePtr, count: Int(count))))
|
||||
}
|
||||
|
||||
private func writeStub(_ cookie: UnsafeMutableRawPointer?,
|
||||
_ bytePtr: UnsafePointer<Int8>?,
|
||||
_ count: Int32) -> Int32 {
|
||||
guard let cookie = cookie, let bytePtr = bytePtr else { return 0 }
|
||||
return Int32(fileFromCookie(cookie: cookie).writeData(
|
||||
buffer: UnsafeRawBufferPointer(start: bytePtr, count: Int(count))))
|
||||
}
|
||||
|
||||
private func seekStub(_ cookie: UnsafeMutableRawPointer?,
|
||||
_ offset: fpos_t,
|
||||
_ whence: Int32) -> fpos_t {
|
||||
guard let cookie = cookie else { return 0 }
|
||||
return fpos_t(fileFromCookie(cookie: cookie).seek(offset: Int(offset), whence: whence))
|
||||
}
|
||||
|
||||
#else
|
||||
private func readStub(_ cookie: UnsafeMutableRawPointer?,
|
||||
_ bytePtr: UnsafeMutablePointer<Int8>?,
|
||||
_ count: Int) -> Int {
|
||||
guard let cookie = cookie, let bytePtr = bytePtr else { return 0 }
|
||||
return fileFromCookie(cookie: cookie).readData(
|
||||
buffer: UnsafeMutableRawBufferPointer(start: bytePtr, count: count))
|
||||
}
|
||||
|
||||
private func writeStub(_ cookie: UnsafeMutableRawPointer?,
|
||||
_ bytePtr: UnsafePointer<Int8>?,
|
||||
_ count: Int) -> Int {
|
||||
guard let cookie = cookie, let bytePtr = bytePtr else { return 0 }
|
||||
return fileFromCookie(cookie: cookie).writeData(
|
||||
buffer: UnsafeRawBufferPointer(start: bytePtr, count: count))
|
||||
}
|
||||
|
||||
private func seekStub(_ cookie: UnsafeMutableRawPointer?,
|
||||
_ offset: UnsafeMutablePointer<Int>?,
|
||||
_ whence: Int32) -> Int32 {
|
||||
guard let cookie = cookie, let offset = offset else { return 0 }
|
||||
let result = fileFromCookie(cookie: cookie).seek(offset: Int(offset.pointee), whence: whence)
|
||||
if result >= 0 {
|
||||
offset.pointee = result
|
||||
return 0
|
||||
} else {
|
||||
return -1
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
@ -1,133 +0,0 @@
|
||||
//
|
||||
// Archive+Reading.swift
|
||||
// ZIPFoundation
|
||||
//
|
||||
// Copyright © 2017-2020 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension Archive {
|
||||
/// Read a ZIP `Entry` from the receiver and write it to `url`.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - entry: The ZIP `Entry` to read.
|
||||
/// - 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.
|
||||
/// - 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: UInt32 = defaultReadChunkSize, skipCRC32: Bool = false,
|
||||
progress: Progress? = nil) throws -> CRC32 {
|
||||
let fileManager = FileManager()
|
||||
var checksum = CRC32(0)
|
||||
switch entry.type {
|
||||
case .file:
|
||||
guard !fileManager.itemExists(at: url) else {
|
||||
throw CocoaError(.fileWriteFileExists, userInfo: [NSFilePathErrorKey: url.path])
|
||||
}
|
||||
try fileManager.createParentDirectoryStructure(for: url)
|
||||
let destinationRepresentation = fileManager.fileSystemRepresentation(withPath: url.path)
|
||||
guard let destinationFile: UnsafeMutablePointer<FILE> = fopen(destinationRepresentation, "wb+") else {
|
||||
throw CocoaError(.fileNoSuchFile)
|
||||
}
|
||||
defer { fclose(destinationFile) }
|
||||
let consumer = { _ = try Data.write(chunk: $0, to: destinationFile) }
|
||||
checksum = try self.extract(entry, bufferSize: bufferSize, skipCRC32: skipCRC32,
|
||||
progress: progress, consumer: consumer)
|
||||
case .directory:
|
||||
let consumer = { (_: Data) in
|
||||
try fileManager.createDirectory(at: url, withIntermediateDirectories: true, attributes: nil)
|
||||
}
|
||||
checksum = try self.extract(entry, bufferSize: bufferSize, skipCRC32: skipCRC32,
|
||||
progress: progress, consumer: consumer)
|
||||
case .symlink:
|
||||
guard !fileManager.itemExists(at: url) 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 }
|
||||
try fileManager.createParentDirectoryStructure(for: url)
|
||||
try fileManager.createSymbolicLink(atPath: url.path, withDestinationPath: linkPath)
|
||||
}
|
||||
checksum = try self.extract(entry, bufferSize: bufferSize, skipCRC32: skipCRC32,
|
||||
progress: progress, consumer: consumer)
|
||||
}
|
||||
let attributes = FileManager.attributes(from: entry)
|
||||
try fileManager.setAttributes(attributes, ofItemAtPath: url.path)
|
||||
return checksum
|
||||
}
|
||||
|
||||
/// Read a ZIP `Entry` from the receiver and forward its contents to a `Consumer` closure.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - entry: The ZIP `Entry` to read.
|
||||
/// - 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.
|
||||
/// - progress: A progress object that can be used to track or cancel the extract operation.
|
||||
/// - consumer: A closure that consumes contents of `Entry` as `Data` chunks.
|
||||
/// - 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, bufferSize: UInt32 = defaultReadChunkSize, skipCRC32: Bool = false,
|
||||
progress: Progress? = nil, consumer: Consumer) throws -> CRC32 {
|
||||
var checksum = CRC32(0)
|
||||
let localFileHeader = entry.localFileHeader
|
||||
fseek(self.archiveFile, entry.dataOffset, SEEK_SET)
|
||||
progress?.totalUnitCount = self.totalUnitCountForReading(entry)
|
||||
switch entry.type {
|
||||
case .file:
|
||||
guard let compressionMethod = CompressionMethod(rawValue: localFileHeader.compressionMethod) else {
|
||||
throw ArchiveError.invalidCompressionMethod
|
||||
}
|
||||
switch compressionMethod {
|
||||
case .none: checksum = try self.readUncompressed(entry: entry, bufferSize: bufferSize,
|
||||
skipCRC32: skipCRC32, progress: progress, with: consumer)
|
||||
case .deflate: checksum = try self.readCompressed(entry: entry, bufferSize: bufferSize,
|
||||
skipCRC32: skipCRC32, progress: progress, with: consumer)
|
||||
}
|
||||
case .directory:
|
||||
try consumer(Data())
|
||||
progress?.completedUnitCount = self.totalUnitCountForReading(entry)
|
||||
case .symlink:
|
||||
let localFileHeader = entry.localFileHeader
|
||||
let size = Int(localFileHeader.compressedSize)
|
||||
let data = try Data.readChunk(of: size, from: self.archiveFile)
|
||||
checksum = data.crc32(checksum: 0)
|
||||
try consumer(data)
|
||||
progress?.completedUnitCount = self.totalUnitCountForReading(entry)
|
||||
}
|
||||
return checksum
|
||||
}
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
private func readUncompressed(entry: Entry, bufferSize: UInt32, skipCRC32: Bool,
|
||||
progress: Progress? = nil, with consumer: Consumer) throws -> CRC32 {
|
||||
let size = Int(entry.centralDirectoryStructure.uncompressedSize)
|
||||
return try Data.consumePart(of: size, chunkSize: Int(bufferSize), skipCRC32: skipCRC32,
|
||||
provider: { (_, chunkSize) -> Data in
|
||||
return try Data.readChunk(of: Int(chunkSize), from: self.archiveFile)
|
||||
}, consumer: { (data) in
|
||||
if progress?.isCancelled == true { throw ArchiveError.cancelledOperation }
|
||||
try consumer(data)
|
||||
progress?.completedUnitCount += Int64(data.count)
|
||||
})
|
||||
}
|
||||
|
||||
private func readCompressed(entry: Entry, bufferSize: UInt32, skipCRC32: Bool,
|
||||
progress: Progress? = nil, with consumer: Consumer) throws -> CRC32 {
|
||||
let size = Int(entry.centralDirectoryStructure.compressedSize)
|
||||
return try Data.decompress(size: size, bufferSize: Int(bufferSize), skipCRC32: skipCRC32,
|
||||
provider: { (_, chunkSize) -> Data in
|
||||
return try Data.readChunk(of: chunkSize, from: self.archiveFile)
|
||||
}, consumer: { (data) in
|
||||
if progress?.isCancelled == true { throw ArchiveError.cancelledOperation }
|
||||
try consumer(data)
|
||||
progress?.completedUnitCount += Int64(data.count)
|
||||
})
|
||||
}
|
||||
}
|
@ -1,354 +0,0 @@
|
||||
//
|
||||
// Archive+Writing.swift
|
||||
// ZIPFoundation
|
||||
//
|
||||
// Copyright © 2017-2020 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension Archive {
|
||||
private enum ModifyOperation: Int {
|
||||
case remove = -1
|
||||
case add = 1
|
||||
}
|
||||
|
||||
/// Write files, directories or symlinks to the receiver.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - path: The path that is used to identify an `Entry` within the `Archive` file.
|
||||
/// - baseURL: The base URL of the `Entry` to add.
|
||||
/// The `baseURL` combined with `path` must form a fully qualified file URL.
|
||||
/// - compressionMethod: Indicates the `CompressionMethod` that should be applied to `Entry`.
|
||||
/// By default, no compression will be applied.
|
||||
/// - bufferSize: The maximum size of the write buffer and the compression buffer (if needed).
|
||||
/// - progress: A progress object that can be used to track or cancel the add operation.
|
||||
/// - Throws: An error if the source file cannot be read or the receiver is not writable.
|
||||
public func addEntry(with path: String, relativeTo baseURL: URL, compressionMethod: CompressionMethod = .none,
|
||||
bufferSize: UInt32 = defaultWriteChunkSize, progress: Progress? = nil) throws {
|
||||
let fileManager = FileManager()
|
||||
let entryURL = baseURL.appendingPathComponent(path)
|
||||
guard fileManager.itemExists(at: entryURL) else {
|
||||
throw CocoaError(.fileReadNoSuchFile, userInfo: [NSFilePathErrorKey: entryURL.path])
|
||||
}
|
||||
let type = try FileManager.typeForItem(at: entryURL)
|
||||
// symlinks do not need to be readable
|
||||
guard type == .symlink || fileManager.isReadableFile(atPath: entryURL.path) else {
|
||||
throw CocoaError(.fileReadNoPermission, userInfo: [NSFilePathErrorKey: url.path])
|
||||
}
|
||||
let modDate = try FileManager.fileModificationDateTimeForItem(at: entryURL)
|
||||
let uncompressedSize = type == .directory ? 0 : try FileManager.fileSizeForItem(at: entryURL)
|
||||
let permissions = try FileManager.permissionsForItem(at: entryURL)
|
||||
var provider: Provider
|
||||
switch type {
|
||||
case .file:
|
||||
let entryFileSystemRepresentation = fileManager.fileSystemRepresentation(withPath: entryURL.path)
|
||||
guard let entryFile: UnsafeMutablePointer<FILE> = fopen(entryFileSystemRepresentation, "rb") else {
|
||||
throw CocoaError(.fileNoSuchFile)
|
||||
}
|
||||
defer { fclose(entryFile) }
|
||||
provider = { _, _ in return try Data.readChunk(of: Int(bufferSize), from: entryFile) }
|
||||
try self.addEntry(with: path, type: type, uncompressedSize: uncompressedSize,
|
||||
modificationDate: modDate, permissions: permissions,
|
||||
compressionMethod: compressionMethod, bufferSize: bufferSize,
|
||||
progress: progress, provider: provider)
|
||||
case .directory:
|
||||
provider = { _, _ in return Data() }
|
||||
try self.addEntry(with: path.hasSuffix("/") ? path : path + "/",
|
||||
type: type, uncompressedSize: uncompressedSize,
|
||||
modificationDate: modDate, permissions: permissions,
|
||||
compressionMethod: compressionMethod, bufferSize: bufferSize,
|
||||
progress: progress, provider: provider)
|
||||
case .symlink:
|
||||
provider = { _, _ -> Data in
|
||||
let linkDestination = try fileManager.destinationOfSymbolicLink(atPath: entryURL.path)
|
||||
let linkFileSystemRepresentation = fileManager.fileSystemRepresentation(withPath: linkDestination)
|
||||
let linkLength = Int(strlen(linkFileSystemRepresentation))
|
||||
let linkBuffer = UnsafeBufferPointer(start: linkFileSystemRepresentation, count: linkLength)
|
||||
return Data(buffer: linkBuffer)
|
||||
}
|
||||
try self.addEntry(with: path, type: type, uncompressedSize: uncompressedSize,
|
||||
modificationDate: modDate, permissions: permissions,
|
||||
compressionMethod: compressionMethod, bufferSize: bufferSize,
|
||||
progress: progress, provider: provider)
|
||||
}
|
||||
}
|
||||
|
||||
/// Write files, directories or symlinks to the receiver.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - path: The path that is used to identify an `Entry` within the `Archive` file.
|
||||
/// - type: Indicates the `Entry.EntryType` of the added content.
|
||||
/// - uncompressedSize: The uncompressed size of the data that is going to be added with `provider`.
|
||||
/// - modificationDate: A `Date` describing the file modification date of the `Entry`.
|
||||
/// Default is the current `Date`.
|
||||
/// - permissions: POSIX file permissions for the `Entry`.
|
||||
/// Default is `0`o`644` for files and symlinks and `0`o`755` for directories.
|
||||
/// - compressionMethod: Indicates the `CompressionMethod` that should be applied to `Entry`.
|
||||
/// By default, no compression will be applied.
|
||||
/// - bufferSize: The maximum size of the write buffer and the compression buffer (if needed).
|
||||
/// - progress: A progress object that can be used to track or cancel the add operation.
|
||||
/// - provider: A closure that accepts a position and a chunk size. Returns a `Data` chunk.
|
||||
/// - Throws: An error if the source data is invalid or the receiver is not writable.
|
||||
public func addEntry(with path: String, type: Entry.EntryType, uncompressedSize: UInt32,
|
||||
modificationDate: Date = Date(), permissions: UInt16? = nil,
|
||||
compressionMethod: CompressionMethod = .none, bufferSize: UInt32 = defaultWriteChunkSize,
|
||||
progress: Progress? = nil, provider: Provider) throws {
|
||||
guard self.accessMode != .read else { throw ArchiveError.unwritableArchive }
|
||||
// Directories and symlinks cannot be compressed
|
||||
let compressionMethod = type == .file ? compressionMethod : .none
|
||||
progress?.totalUnitCount = type == .directory ? defaultDirectoryUnitCount : Int64(uncompressedSize)
|
||||
var endOfCentralDirRecord = self.endOfCentralDirectoryRecord
|
||||
var startOfCD = Int(endOfCentralDirRecord.offsetToStartOfCentralDirectory)
|
||||
fseek(self.archiveFile, startOfCD, SEEK_SET)
|
||||
let existingCentralDirData = try Data.readChunk(of: Int(endOfCentralDirRecord.sizeOfCentralDirectory),
|
||||
from: self.archiveFile)
|
||||
fseek(self.archiveFile, startOfCD, SEEK_SET)
|
||||
let localFileHeaderStart = ftell(self.archiveFile)
|
||||
let modDateTime = modificationDate.fileModificationDateTime
|
||||
defer { fflush(self.archiveFile) }
|
||||
do {
|
||||
var localFileHeader = try self.writeLocalFileHeader(path: path, compressionMethod: compressionMethod,
|
||||
size: (uncompressedSize, 0), checksum: 0,
|
||||
modificationDateTime: modDateTime)
|
||||
let (written, checksum) = try self.writeEntry(localFileHeader: localFileHeader, type: type,
|
||||
compressionMethod: compressionMethod, bufferSize: bufferSize,
|
||||
progress: progress, provider: provider)
|
||||
startOfCD = ftell(self.archiveFile)
|
||||
fseek(self.archiveFile, localFileHeaderStart, SEEK_SET)
|
||||
// Write the local file header a second time. Now with compressedSize (if applicable) and a valid checksum.
|
||||
localFileHeader = try self.writeLocalFileHeader(path: path, compressionMethod: compressionMethod,
|
||||
size: (uncompressedSize, written),
|
||||
checksum: checksum, modificationDateTime: modDateTime)
|
||||
fseek(self.archiveFile, startOfCD, SEEK_SET)
|
||||
_ = try Data.write(chunk: existingCentralDirData, to: self.archiveFile)
|
||||
let permissions = permissions ?? (type == .directory ? defaultDirectoryPermissions :defaultFilePermissions)
|
||||
let externalAttributes = FileManager.externalFileAttributesForEntry(of: type, permissions: permissions)
|
||||
let offset = UInt32(localFileHeaderStart)
|
||||
let centralDir = try self.writeCentralDirectoryStructure(localFileHeader: localFileHeader,
|
||||
relativeOffset: offset,
|
||||
externalFileAttributes: externalAttributes)
|
||||
if startOfCD > UINT32_MAX { throw ArchiveError.invalidStartOfCentralDirectoryOffset }
|
||||
endOfCentralDirRecord = try self.writeEndOfCentralDirectory(centralDirectoryStructure: centralDir,
|
||||
startOfCentralDirectory: UInt32(startOfCD),
|
||||
operation: .add)
|
||||
self.endOfCentralDirectoryRecord = endOfCentralDirRecord
|
||||
} catch ArchiveError.cancelledOperation {
|
||||
try rollback(localFileHeaderStart, existingCentralDirData, endOfCentralDirRecord)
|
||||
throw ArchiveError.cancelledOperation
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove a ZIP `Entry` from the receiver.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - entry: The `Entry` to remove.
|
||||
/// - bufferSize: The maximum size for the read and write buffers used during removal.
|
||||
/// - progress: A progress object that can be used to track or cancel the remove operation.
|
||||
/// - Throws: An error if the `Entry` is malformed or the receiver is not writable.
|
||||
public func remove(_ entry: Entry, bufferSize: UInt32 = defaultReadChunkSize, progress: Progress? = nil) throws {
|
||||
let manager = FileManager()
|
||||
let tempDir = self.uniqueTemporaryDirectoryURL()
|
||||
defer { try? manager.removeItem(at: tempDir) }
|
||||
let uniqueString = ProcessInfo.processInfo.globallyUniqueString
|
||||
let tempArchiveURL = tempDir.appendingPathComponent(uniqueString)
|
||||
do { try manager.createParentDirectoryStructure(for: tempArchiveURL) } catch {
|
||||
throw ArchiveError.unwritableArchive }
|
||||
guard let tempArchive = Archive(url: tempArchiveURL, accessMode: .create) else {
|
||||
throw ArchiveError.unwritableArchive
|
||||
}
|
||||
progress?.totalUnitCount = self.totalUnitCountForRemoving(entry)
|
||||
var centralDirectoryData = Data()
|
||||
var offset = 0
|
||||
for currentEntry in self {
|
||||
let centralDirectoryStructure = currentEntry.centralDirectoryStructure
|
||||
if currentEntry != entry {
|
||||
let entryStart = Int(currentEntry.centralDirectoryStructure.relativeOffsetOfLocalHeader)
|
||||
fseek(self.archiveFile, entryStart, SEEK_SET)
|
||||
let provider: Provider = { (_, chunkSize) -> Data in
|
||||
return try Data.readChunk(of: Int(chunkSize), from: self.archiveFile)
|
||||
}
|
||||
let consumer: Consumer = {
|
||||
if progress?.isCancelled == true { throw ArchiveError.cancelledOperation }
|
||||
_ = try Data.write(chunk: $0, to: tempArchive.archiveFile)
|
||||
progress?.completedUnitCount += Int64($0.count)
|
||||
}
|
||||
_ = try Data.consumePart(of: Int(currentEntry.localSize), chunkSize: Int(bufferSize),
|
||||
provider: provider, consumer: consumer)
|
||||
let centralDir = CentralDirectoryStructure(centralDirectoryStructure: centralDirectoryStructure,
|
||||
offset: UInt32(offset))
|
||||
centralDirectoryData.append(centralDir.data)
|
||||
} else { offset = currentEntry.localSize }
|
||||
}
|
||||
let startOfCentralDirectory = ftell(tempArchive.archiveFile)
|
||||
_ = try Data.write(chunk: centralDirectoryData, to: tempArchive.archiveFile)
|
||||
tempArchive.endOfCentralDirectoryRecord = self.endOfCentralDirectoryRecord
|
||||
let endOfCentralDirectoryRecord = try
|
||||
tempArchive.writeEndOfCentralDirectory(centralDirectoryStructure: entry.centralDirectoryStructure,
|
||||
startOfCentralDirectory: UInt32(startOfCentralDirectory),
|
||||
operation: .remove)
|
||||
tempArchive.endOfCentralDirectoryRecord = endOfCentralDirectoryRecord
|
||||
self.endOfCentralDirectoryRecord = endOfCentralDirectoryRecord
|
||||
fflush(tempArchive.archiveFile)
|
||||
try self.replaceCurrentArchiveWithArchive(at: tempArchive.url)
|
||||
}
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
func uniqueTemporaryDirectoryURL() -> URL {
|
||||
#if swift(>=5.0) || os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
|
||||
if let tempDir = try? FileManager().url(for: .itemReplacementDirectory, in: .userDomainMask,
|
||||
appropriateFor: self.url, create: true) {
|
||||
return tempDir
|
||||
}
|
||||
#endif
|
||||
|
||||
return URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(
|
||||
ProcessInfo.processInfo.globallyUniqueString)
|
||||
}
|
||||
|
||||
func replaceCurrentArchiveWithArchive(at URL: URL) throws {
|
||||
fclose(self.archiveFile)
|
||||
let fileManager = FileManager()
|
||||
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
|
||||
do {
|
||||
_ = try fileManager.replaceItemAt(self.url, withItemAt: URL)
|
||||
} catch {
|
||||
_ = try fileManager.removeItem(at: self.url)
|
||||
_ = try fileManager.moveItem(at: URL, to: self.url)
|
||||
}
|
||||
#else
|
||||
_ = try fileManager.removeItem(at: self.url)
|
||||
_ = try fileManager.moveItem(at: URL, to: self.url)
|
||||
#endif
|
||||
let fileSystemRepresentation = fileManager.fileSystemRepresentation(withPath: self.url.path)
|
||||
self.archiveFile = fopen(fileSystemRepresentation, "rb+")
|
||||
}
|
||||
|
||||
private func writeLocalFileHeader(path: String, compressionMethod: CompressionMethod,
|
||||
size: (uncompressed: UInt32, compressed: UInt32),
|
||||
checksum: CRC32,
|
||||
modificationDateTime: (UInt16, UInt16)) throws -> LocalFileHeader {
|
||||
// We always set Bit 11 in generalPurposeBitFlag, which indicates an UTF-8 encoded path.
|
||||
guard let fileNameData = path.data(using: .utf8) else { throw ArchiveError.invalidEntryPath }
|
||||
|
||||
let localFileHeader = LocalFileHeader(versionNeededToExtract: UInt16(20), generalPurposeBitFlag: UInt16(2048),
|
||||
compressionMethod: compressionMethod.rawValue,
|
||||
lastModFileTime: modificationDateTime.1,
|
||||
lastModFileDate: modificationDateTime.0, crc32: checksum,
|
||||
compressedSize: size.compressed, uncompressedSize: size.uncompressed,
|
||||
fileNameLength: UInt16(fileNameData.count), extraFieldLength: UInt16(0),
|
||||
fileNameData: fileNameData, extraFieldData: Data())
|
||||
_ = try Data.write(chunk: localFileHeader.data, to: self.archiveFile)
|
||||
return localFileHeader
|
||||
}
|
||||
|
||||
private func writeEntry(localFileHeader: LocalFileHeader, type: Entry.EntryType,
|
||||
compressionMethod: CompressionMethod, bufferSize: UInt32, progress: Progress? = nil,
|
||||
provider: Provider) throws -> (sizeWritten: UInt32, crc32: CRC32) {
|
||||
var checksum = CRC32(0)
|
||||
var sizeWritten = UInt32(0)
|
||||
switch type {
|
||||
case .file:
|
||||
switch compressionMethod {
|
||||
case .none:
|
||||
(sizeWritten, checksum) = try self.writeUncompressed(size: localFileHeader.uncompressedSize,
|
||||
bufferSize: bufferSize,
|
||||
progress: progress, provider: provider)
|
||||
case .deflate:
|
||||
(sizeWritten, checksum) = try self.writeCompressed(size: localFileHeader.uncompressedSize,
|
||||
bufferSize: bufferSize,
|
||||
progress: progress, provider: provider)
|
||||
}
|
||||
case .directory:
|
||||
_ = try provider(0, 0)
|
||||
if let progress = progress { progress.completedUnitCount = progress.totalUnitCount }
|
||||
case .symlink:
|
||||
(sizeWritten, checksum) = try self.writeSymbolicLink(size: localFileHeader.uncompressedSize,
|
||||
provider: provider)
|
||||
if let progress = progress { progress.completedUnitCount = progress.totalUnitCount }
|
||||
}
|
||||
return (sizeWritten, checksum)
|
||||
}
|
||||
|
||||
private func writeUncompressed(size: UInt32, bufferSize: UInt32, progress: Progress? = nil,
|
||||
provider: Provider) throws -> (sizeWritten: UInt32, checksum: CRC32) {
|
||||
var position = 0
|
||||
var sizeWritten = 0
|
||||
var checksum = CRC32(0)
|
||||
while position < size {
|
||||
if progress?.isCancelled == true { throw ArchiveError.cancelledOperation }
|
||||
let readSize = (Int(size) - position) >= bufferSize ? Int(bufferSize) : (Int(size) - position)
|
||||
let entryChunk = try provider(Int(position), Int(readSize))
|
||||
checksum = entryChunk.crc32(checksum: checksum)
|
||||
sizeWritten += try Data.write(chunk: entryChunk, to: self.archiveFile)
|
||||
position += Int(bufferSize)
|
||||
progress?.completedUnitCount = Int64(sizeWritten)
|
||||
}
|
||||
return (UInt32(sizeWritten), checksum)
|
||||
}
|
||||
|
||||
private func writeCompressed(size: UInt32, bufferSize: UInt32, progress: Progress? = nil,
|
||||
provider: Provider) throws -> (sizeWritten: UInt32, checksum: CRC32) {
|
||||
var sizeWritten = 0
|
||||
let consumer: Consumer = { data in sizeWritten += try Data.write(chunk: data, to: self.archiveFile) }
|
||||
let checksum = try Data.compress(size: Int(size), bufferSize: Int(bufferSize),
|
||||
provider: { (position, size) -> Data in
|
||||
if progress?.isCancelled == true { throw ArchiveError.cancelledOperation }
|
||||
let data = try provider(position, size)
|
||||
progress?.completedUnitCount += Int64(data.count)
|
||||
return data
|
||||
}, consumer: consumer)
|
||||
return(UInt32(sizeWritten), checksum)
|
||||
}
|
||||
|
||||
private func writeSymbolicLink(size: UInt32, provider: Provider) throws -> (sizeWritten: UInt32, checksum: CRC32) {
|
||||
let linkData = try provider(0, Int(size))
|
||||
let checksum = linkData.crc32(checksum: 0)
|
||||
let sizeWritten = try Data.write(chunk: linkData, to: self.archiveFile)
|
||||
return (UInt32(sizeWritten), checksum)
|
||||
}
|
||||
|
||||
private func writeCentralDirectoryStructure(localFileHeader: LocalFileHeader, relativeOffset: UInt32,
|
||||
externalFileAttributes: UInt32) throws -> CentralDirectoryStructure {
|
||||
let centralDirectory = CentralDirectoryStructure(localFileHeader: localFileHeader,
|
||||
fileAttributes: externalFileAttributes,
|
||||
relativeOffset: relativeOffset)
|
||||
_ = try Data.write(chunk: centralDirectory.data, to: self.archiveFile)
|
||||
return centralDirectory
|
||||
}
|
||||
|
||||
private func writeEndOfCentralDirectory(centralDirectoryStructure: CentralDirectoryStructure,
|
||||
startOfCentralDirectory: UInt32,
|
||||
operation: ModifyOperation) throws -> EndOfCentralDirectoryRecord {
|
||||
var record = self.endOfCentralDirectoryRecord
|
||||
let countChange = operation.rawValue
|
||||
var dataLength = Int(centralDirectoryStructure.extraFieldLength)
|
||||
dataLength += Int(centralDirectoryStructure.fileNameLength)
|
||||
dataLength += Int(centralDirectoryStructure.fileCommentLength)
|
||||
let centralDirectoryDataLengthChange = operation.rawValue * (dataLength + CentralDirectoryStructure.size)
|
||||
var updatedSizeOfCentralDirectory = Int(record.sizeOfCentralDirectory)
|
||||
updatedSizeOfCentralDirectory += centralDirectoryDataLengthChange
|
||||
let numberOfEntriesOnDisk = UInt16(Int(record.totalNumberOfEntriesOnDisk) + countChange)
|
||||
let numberOfEntriesInCentralDirectory = UInt16(Int(record.totalNumberOfEntriesInCentralDirectory) + countChange)
|
||||
record = EndOfCentralDirectoryRecord(record: record, numberOfEntriesOnDisk: numberOfEntriesOnDisk,
|
||||
numberOfEntriesInCentralDirectory: numberOfEntriesInCentralDirectory,
|
||||
updatedSizeOfCentralDirectory: UInt32(updatedSizeOfCentralDirectory),
|
||||
startOfCentralDirectory: startOfCentralDirectory)
|
||||
_ = try Data.write(chunk: record.data, to: self.archiveFile)
|
||||
return record
|
||||
}
|
||||
|
||||
private func rollback(_ localFileHeaderStart: Int,
|
||||
_ existingCentralDirectoryData: Data,
|
||||
_ endOfCentralDirRecord: EndOfCentralDirectoryRecord) throws {
|
||||
fflush(self.archiveFile)
|
||||
ftruncate(fileno(self.archiveFile), off_t(localFileHeaderStart))
|
||||
fseek(self.archiveFile, localFileHeaderStart, SEEK_SET)
|
||||
_ = try Data.write(chunk: existingCentralDirectoryData, to: self.archiveFile)
|
||||
_ = try Data.write(chunk: endOfCentralDirRecord.data, to: self.archiveFile)
|
||||
}
|
||||
}
|
398
third-party/ZIPFoundation/Sources/Archive.swift
vendored
398
third-party/ZIPFoundation/Sources/Archive.swift
vendored
@ -1,398 +0,0 @@
|
||||
//
|
||||
// Archive.swift
|
||||
// ZIPFoundation
|
||||
//
|
||||
// Copyright © 2017-2020 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// The default chunk size when reading entry data from an archive.
|
||||
public let defaultReadChunkSize = UInt32(16*1024)
|
||||
/// The default chunk size when writing entry data to an archive.
|
||||
public let defaultWriteChunkSize = defaultReadChunkSize
|
||||
/// The default permissions for newly added entries.
|
||||
public let defaultFilePermissions = UInt16(0o644)
|
||||
public let defaultDirectoryPermissions = UInt16(0o755)
|
||||
let defaultPOSIXBufferSize = defaultReadChunkSize
|
||||
let defaultDirectoryUnitCount = Int64(1)
|
||||
let minDirectoryEndOffset = 22
|
||||
let maxDirectoryEndOffset = 66000
|
||||
let endOfCentralDirectoryStructSignature = 0x06054b50
|
||||
let localFileHeaderStructSignature = 0x04034b50
|
||||
let dataDescriptorStructSignature = 0x08074b50
|
||||
let centralDirectoryStructSignature = 0x02014b50
|
||||
|
||||
/// The compression method of an `Entry` in a ZIP `Archive`.
|
||||
public enum CompressionMethod: UInt16 {
|
||||
/// Indicates that an `Entry` has no compression applied to its contents.
|
||||
case none = 0
|
||||
/// Indicates that contents of an `Entry` have been compressed with a zlib compatible Deflate algorithm.
|
||||
case deflate = 8
|
||||
}
|
||||
|
||||
/// A sequence of uncompressed or compressed ZIP entries.
|
||||
///
|
||||
/// You use an `Archive` to create, read or update ZIP files.
|
||||
/// To read an existing ZIP file, you have to pass in an existing file `URL` and `AccessMode.read`:
|
||||
///
|
||||
/// var archiveURL = URL(fileURLWithPath: "/path/file.zip")
|
||||
/// var archive = Archive(url: archiveURL, accessMode: .read)
|
||||
///
|
||||
/// An `Archive` is a sequence of entries. You can
|
||||
/// iterate over an archive using a `for`-`in` loop to get access to individual `Entry` objects:
|
||||
///
|
||||
/// for entry in archive {
|
||||
/// print(entry.path)
|
||||
/// }
|
||||
///
|
||||
/// Each `Entry` in an `Archive` is represented by its `path`. You can
|
||||
/// use `path` to retrieve the corresponding `Entry` from an `Archive` via subscripting:
|
||||
///
|
||||
/// let entry = archive['/path/file.txt']
|
||||
///
|
||||
/// To create a new `Archive`, pass in a non-existing file URL and `AccessMode.create`. To modify an
|
||||
/// existing `Archive` use `AccessMode.update`:
|
||||
///
|
||||
/// var archiveURL = URL(fileURLWithPath: "/path/file.zip")
|
||||
/// var archive = Archive(url: archiveURL, accessMode: .update)
|
||||
/// try archive?.addEntry("test.txt", relativeTo: baseURL, compressionMethod: .deflate)
|
||||
public final class Archive: Sequence {
|
||||
typealias LocalFileHeader = Entry.LocalFileHeader
|
||||
typealias DataDescriptor = Entry.DataDescriptor
|
||||
typealias CentralDirectoryStructure = Entry.CentralDirectoryStructure
|
||||
|
||||
/// An error that occurs during reading, creating or updating a ZIP file.
|
||||
public enum ArchiveError: Error {
|
||||
/// Thrown when an archive file is either damaged or inaccessible.
|
||||
case unreadableArchive
|
||||
/// Thrown when an archive is either opened with AccessMode.read or the destination file is unwritable.
|
||||
case unwritableArchive
|
||||
/// Thrown when the path of an `Entry` cannot be stored in an archive.
|
||||
case invalidEntryPath
|
||||
/// Thrown when an `Entry` can't be stored in the archive with the proposed compression method.
|
||||
case invalidCompressionMethod
|
||||
/// Thrown when the start of the central directory exceeds `UINT32_MAX`
|
||||
case invalidStartOfCentralDirectoryOffset
|
||||
/// Thrown when an archive does not contain the required End of Central Directory Record.
|
||||
case missingEndOfCentralDirectoryRecord
|
||||
/// Thrown when an extract, add or remove operation was canceled.
|
||||
case cancelledOperation
|
||||
}
|
||||
|
||||
/// The access mode for an `Archive`.
|
||||
public enum AccessMode: UInt {
|
||||
/// Indicates that a newly instantiated `Archive` should create its backing file.
|
||||
case create
|
||||
/// Indicates that a newly instantiated `Archive` should read from an existing backing file.
|
||||
case read
|
||||
/// Indicates that a newly instantiated `Archive` should update an existing backing file.
|
||||
case update
|
||||
}
|
||||
|
||||
struct EndOfCentralDirectoryRecord: DataSerializable {
|
||||
let endOfCentralDirectorySignature = UInt32(endOfCentralDirectoryStructSignature)
|
||||
let numberOfDisk: UInt16
|
||||
let numberOfDiskStart: UInt16
|
||||
let totalNumberOfEntriesOnDisk: UInt16
|
||||
let totalNumberOfEntriesInCentralDirectory: UInt16
|
||||
let sizeOfCentralDirectory: UInt32
|
||||
let offsetToStartOfCentralDirectory: UInt32
|
||||
let zipFileCommentLength: UInt16
|
||||
let zipFileCommentData: Data
|
||||
static let size = 22
|
||||
}
|
||||
|
||||
private var preferredEncoding: String.Encoding?
|
||||
/// URL of an Archive's backing file.
|
||||
public let url: URL
|
||||
/// Access mode for an archive file.
|
||||
public let accessMode: AccessMode
|
||||
var archiveFile: UnsafeMutablePointer<FILE>
|
||||
var endOfCentralDirectoryRecord: EndOfCentralDirectoryRecord
|
||||
|
||||
/// Initializes a new ZIP `Archive`.
|
||||
///
|
||||
/// You can use this initalizer to create new archive files or to read and update existing ones.
|
||||
/// The `mode` parameter indicates the intended usage of the archive: `.read`, `.create` or `.update`.
|
||||
/// - Parameters:
|
||||
/// - url: File URL to the receivers backing file.
|
||||
/// - mode: Access mode of the receiver.
|
||||
/// - preferredEncoding: Encoding for entry paths. Overrides the encoding specified in the archive.
|
||||
/// This encoding is only used when _decoding_ paths from the receiver.
|
||||
/// Paths of entries added with `addEntry` are always UTF-8 encoded.
|
||||
/// - Returns: An archive initialized with a backing file at the passed in file URL and the given access mode
|
||||
/// or `nil` if the following criteria are not met:
|
||||
/// - Note:
|
||||
/// - The file URL _must_ point to an existing file for `AccessMode.read`.
|
||||
/// - The file URL _must_ point to a non-existing file for `AccessMode.create`.
|
||||
/// - The file URL _must_ point to an existing file for `AccessMode.update`.
|
||||
public init?(url: URL, accessMode mode: AccessMode, preferredEncoding: String.Encoding? = nil) {
|
||||
self.url = url
|
||||
self.accessMode = mode
|
||||
self.preferredEncoding = preferredEncoding
|
||||
guard let (archiveFile, endOfCentralDirectoryRecord) = Archive.configureFileBacking(for: url, mode: mode) else {
|
||||
return nil
|
||||
}
|
||||
self.archiveFile = archiveFile
|
||||
self.endOfCentralDirectoryRecord = endOfCentralDirectoryRecord
|
||||
setvbuf(self.archiveFile, nil, _IOFBF, Int(defaultPOSIXBufferSize))
|
||||
}
|
||||
|
||||
#if swift(>=5.0)
|
||||
var memoryFile: MemoryFile?
|
||||
|
||||
/// Initializes a new in-memory ZIP `Archive`.
|
||||
///
|
||||
/// You can use this initalizer to create new in-memory archive files or to read and update existing ones.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - data: `Data` object used as backing for in-memory archives.
|
||||
/// - mode: Access mode of the receiver.
|
||||
/// - preferredEncoding: Encoding for entry paths. Overrides the encoding specified in the archive.
|
||||
/// This encoding is only used when _decoding_ paths from the receiver.
|
||||
/// Paths of entries added with `addEntry` are always UTF-8 encoded.
|
||||
/// - Returns: An in-memory archive initialized with passed in backing data.
|
||||
/// - Note:
|
||||
/// - The backing `data` _must_ contain a valid ZIP archive for `AccessMode.read` and `AccessMode.update`.
|
||||
/// - The backing `data` _must_ be empty (or omitted) for `AccessMode.create`.
|
||||
public init?(data: Data = Data(), accessMode mode: AccessMode, preferredEncoding: String.Encoding? = nil) {
|
||||
guard let url = URL(string: "memory:"),
|
||||
let (archiveFile, memoryFile) = Archive.configureMemoryBacking(for: data, mode: mode) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
self.url = url
|
||||
self.accessMode = mode
|
||||
self.preferredEncoding = preferredEncoding
|
||||
self.archiveFile = archiveFile
|
||||
self.memoryFile = memoryFile
|
||||
guard let endOfCentralDirectoryRecord = Archive.scanForEndOfCentralDirectoryRecord(in: archiveFile)
|
||||
else {
|
||||
fclose(self.archiveFile)
|
||||
return nil
|
||||
}
|
||||
self.endOfCentralDirectoryRecord = endOfCentralDirectoryRecord
|
||||
}
|
||||
#endif
|
||||
|
||||
deinit {
|
||||
fclose(self.archiveFile)
|
||||
}
|
||||
|
||||
public func makeIterator() -> AnyIterator<Entry> {
|
||||
let endOfCentralDirectoryRecord = self.endOfCentralDirectoryRecord
|
||||
var directoryIndex = Int(endOfCentralDirectoryRecord.offsetToStartOfCentralDirectory)
|
||||
var index = 0
|
||||
return AnyIterator {
|
||||
guard index < Int(endOfCentralDirectoryRecord.totalNumberOfEntriesInCentralDirectory) else { return nil }
|
||||
guard let centralDirStruct: CentralDirectoryStructure = Data.readStruct(from: self.archiveFile,
|
||||
at: directoryIndex) else {
|
||||
return nil
|
||||
}
|
||||
let offset = Int(centralDirStruct.relativeOffsetOfLocalHeader)
|
||||
guard let localFileHeader: LocalFileHeader = Data.readStruct(from: self.archiveFile,
|
||||
at: offset) else { return nil }
|
||||
var dataDescriptor: DataDescriptor?
|
||||
if centralDirStruct.usesDataDescriptor {
|
||||
let additionalSize = Int(localFileHeader.fileNameLength) + Int(localFileHeader.extraFieldLength)
|
||||
let isCompressed = centralDirStruct.compressionMethod != CompressionMethod.none.rawValue
|
||||
let dataSize = isCompressed ? centralDirStruct.compressedSize : centralDirStruct.uncompressedSize
|
||||
let descriptorPosition = offset + LocalFileHeader.size + additionalSize + Int(dataSize)
|
||||
dataDescriptor = Data.readStruct(from: self.archiveFile, at: descriptorPosition)
|
||||
}
|
||||
defer {
|
||||
directoryIndex += CentralDirectoryStructure.size
|
||||
directoryIndex += Int(centralDirStruct.fileNameLength)
|
||||
directoryIndex += Int(centralDirStruct.extraFieldLength)
|
||||
directoryIndex += Int(centralDirStruct.fileCommentLength)
|
||||
index += 1
|
||||
}
|
||||
return Entry(centralDirectoryStructure: centralDirStruct,
|
||||
localFileHeader: localFileHeader, dataDescriptor: dataDescriptor)
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieve the ZIP `Entry` with the given `path` from the receiver.
|
||||
///
|
||||
/// - Note: The ZIP file format specification does not enforce unique paths for entries.
|
||||
/// Therefore an archive can contain multiple entries with the same path. This method
|
||||
/// always returns the first `Entry` with the given `path`.
|
||||
///
|
||||
/// - Parameter path: A relative file path identifiying the corresponding `Entry`.
|
||||
/// - Returns: An `Entry` with the given `path`. Otherwise, `nil`.
|
||||
public subscript(path: String) -> Entry? {
|
||||
if let encoding = preferredEncoding {
|
||||
return self.first { $0.path(using: encoding) == path }
|
||||
}
|
||||
return self.first { $0.path == path }
|
||||
}
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
private static func configureFileBacking(for url: URL, mode: AccessMode)
|
||||
-> (UnsafeMutablePointer<FILE>, EndOfCentralDirectoryRecord)? {
|
||||
let fileManager = FileManager()
|
||||
switch mode {
|
||||
case .read:
|
||||
let fileSystemRepresentation = fileManager.fileSystemRepresentation(withPath: url.path)
|
||||
guard let archiveFile = fopen(fileSystemRepresentation, "rb"),
|
||||
let endOfCentralDirectoryRecord = Archive.scanForEndOfCentralDirectoryRecord(in: archiveFile) else {
|
||||
return nil
|
||||
}
|
||||
return (archiveFile, endOfCentralDirectoryRecord)
|
||||
case .create:
|
||||
let endOfCentralDirectoryRecord = EndOfCentralDirectoryRecord(numberOfDisk: 0, numberOfDiskStart: 0,
|
||||
totalNumberOfEntriesOnDisk: 0,
|
||||
totalNumberOfEntriesInCentralDirectory: 0,
|
||||
sizeOfCentralDirectory: 0,
|
||||
offsetToStartOfCentralDirectory: 0,
|
||||
zipFileCommentLength: 0,
|
||||
zipFileCommentData: Data())
|
||||
do {
|
||||
try endOfCentralDirectoryRecord.data.write(to: url, options: .withoutOverwriting)
|
||||
} catch { return nil }
|
||||
fallthrough
|
||||
case .update:
|
||||
let fileSystemRepresentation = fileManager.fileSystemRepresentation(withPath: url.path)
|
||||
guard let archiveFile = fopen(fileSystemRepresentation, "rb+"),
|
||||
let endOfCentralDirectoryRecord = Archive.scanForEndOfCentralDirectoryRecord(in: archiveFile) else {
|
||||
return nil
|
||||
}
|
||||
fseek(archiveFile, 0, SEEK_SET)
|
||||
return (archiveFile, endOfCentralDirectoryRecord)
|
||||
}
|
||||
}
|
||||
|
||||
private static func scanForEndOfCentralDirectoryRecord(in file: UnsafeMutablePointer<FILE>)
|
||||
-> EndOfCentralDirectoryRecord? {
|
||||
var directoryEnd = 0
|
||||
var index = minDirectoryEndOffset
|
||||
fseek(file, 0, SEEK_END)
|
||||
let archiveLength = ftell(file)
|
||||
while directoryEnd == 0 && index < maxDirectoryEndOffset && index <= archiveLength {
|
||||
fseek(file, archiveLength - index, SEEK_SET)
|
||||
var potentialDirectoryEndTag: UInt32 = UInt32()
|
||||
fread(&potentialDirectoryEndTag, 1, MemoryLayout<UInt32>.size, file)
|
||||
if potentialDirectoryEndTag == UInt32(endOfCentralDirectoryStructSignature) {
|
||||
directoryEnd = archiveLength - index
|
||||
return Data.readStruct(from: file, at: directoryEnd)
|
||||
}
|
||||
index += 1
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
extension Archive {
|
||||
/// The number of the work units that have to be performed when
|
||||
/// removing `entry` from the receiver.
|
||||
///
|
||||
/// - Parameter entry: The entry that will be removed.
|
||||
/// - Returns: The number of the work units.
|
||||
public func totalUnitCountForRemoving(_ entry: Entry) -> Int64 {
|
||||
return Int64(self.endOfCentralDirectoryRecord.offsetToStartOfCentralDirectory
|
||||
- UInt32(entry.localSize))
|
||||
}
|
||||
|
||||
func makeProgressForRemoving(_ entry: Entry) -> Progress {
|
||||
return Progress(totalUnitCount: self.totalUnitCountForRemoving(entry))
|
||||
}
|
||||
|
||||
/// The number of the work units that have to be performed when
|
||||
/// reading `entry` from the receiver.
|
||||
///
|
||||
/// - Parameter entry: The entry that will be read.
|
||||
/// - Returns: The number of the work units.
|
||||
public func totalUnitCountForReading(_ entry: Entry) -> Int64 {
|
||||
switch entry.type {
|
||||
case .file, .symlink:
|
||||
return Int64(entry.uncompressedSize)
|
||||
case .directory:
|
||||
return defaultDirectoryUnitCount
|
||||
}
|
||||
}
|
||||
|
||||
func makeProgressForReading(_ entry: Entry) -> Progress {
|
||||
return Progress(totalUnitCount: self.totalUnitCountForReading(entry))
|
||||
}
|
||||
|
||||
/// The number of the work units that have to be performed when
|
||||
/// adding the file at `url` to the receiver.
|
||||
/// - Parameter entry: The entry that will be removed.
|
||||
/// - Returns: The number of the work units.
|
||||
public func totalUnitCountForAddingItem(at url: URL) -> Int64 {
|
||||
var count = Int64(0)
|
||||
do {
|
||||
let type = try FileManager.typeForItem(at: url)
|
||||
switch type {
|
||||
case .file, .symlink:
|
||||
count = Int64(try FileManager.fileSizeForItem(at: url))
|
||||
case .directory:
|
||||
count = defaultDirectoryUnitCount
|
||||
}
|
||||
} catch { count = -1 }
|
||||
return count
|
||||
}
|
||||
|
||||
func makeProgressForAddingItem(at url: URL) -> Progress {
|
||||
return Progress(totalUnitCount: self.totalUnitCountForAddingItem(at: url))
|
||||
}
|
||||
}
|
||||
|
||||
extension Archive.EndOfCentralDirectoryRecord {
|
||||
var data: Data {
|
||||
var endOfCDSignature = self.endOfCentralDirectorySignature
|
||||
var numberOfDisk = self.numberOfDisk
|
||||
var numberOfDiskStart = self.numberOfDiskStart
|
||||
var totalNumberOfEntriesOnDisk = self.totalNumberOfEntriesOnDisk
|
||||
var totalNumberOfEntriesInCD = self.totalNumberOfEntriesInCentralDirectory
|
||||
var sizeOfCentralDirectory = self.sizeOfCentralDirectory
|
||||
var offsetToStartOfCD = self.offsetToStartOfCentralDirectory
|
||||
var zipFileCommentLength = self.zipFileCommentLength
|
||||
var data = Data()
|
||||
withUnsafePointer(to: &endOfCDSignature, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &numberOfDisk, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &numberOfDiskStart, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &totalNumberOfEntriesOnDisk, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &totalNumberOfEntriesInCD, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &sizeOfCentralDirectory, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &offsetToStartOfCD, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &zipFileCommentLength, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
data.append(self.zipFileCommentData)
|
||||
return data
|
||||
}
|
||||
|
||||
init?(data: Data, additionalDataProvider provider: (Int) throws -> Data) {
|
||||
guard data.count == Archive.EndOfCentralDirectoryRecord.size else { return nil }
|
||||
guard data.scanValue(start: 0) == endOfCentralDirectorySignature else { return nil }
|
||||
self.numberOfDisk = data.scanValue(start: 4)
|
||||
self.numberOfDiskStart = data.scanValue(start: 6)
|
||||
self.totalNumberOfEntriesOnDisk = data.scanValue(start: 8)
|
||||
self.totalNumberOfEntriesInCentralDirectory = data.scanValue(start: 10)
|
||||
self.sizeOfCentralDirectory = data.scanValue(start: 12)
|
||||
self.offsetToStartOfCentralDirectory = data.scanValue(start: 16)
|
||||
self.zipFileCommentLength = data.scanValue(start: 20)
|
||||
guard let commentData = try? provider(Int(self.zipFileCommentLength)) else { return nil }
|
||||
guard commentData.count == Int(self.zipFileCommentLength) else { return nil }
|
||||
self.zipFileCommentData = commentData
|
||||
}
|
||||
|
||||
init(record: Archive.EndOfCentralDirectoryRecord,
|
||||
numberOfEntriesOnDisk: UInt16,
|
||||
numberOfEntriesInCentralDirectory: UInt16,
|
||||
updatedSizeOfCentralDirectory: UInt32,
|
||||
startOfCentralDirectory: UInt32) {
|
||||
numberOfDisk = record.numberOfDisk
|
||||
numberOfDiskStart = record.numberOfDiskStart
|
||||
totalNumberOfEntriesOnDisk = numberOfEntriesOnDisk
|
||||
totalNumberOfEntriesInCentralDirectory = numberOfEntriesInCentralDirectory
|
||||
sizeOfCentralDirectory = updatedSizeOfCentralDirectory
|
||||
offsetToStartOfCentralDirectory = startOfCentralDirectory
|
||||
zipFileCommentLength = record.zipFileCommentLength
|
||||
zipFileCommentData = record.zipFileCommentData
|
||||
}
|
||||
}
|
@ -1,349 +0,0 @@
|
||||
//
|
||||
// Data+Compression.swift
|
||||
// ZIPFoundation
|
||||
//
|
||||
// Copyright © 2017-2020 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// An unsigned 32-Bit Integer representing a checksum.
|
||||
public typealias CRC32 = UInt32
|
||||
/// A custom handler that consumes a `Data` object containing partial entry data.
|
||||
/// - Parameters:
|
||||
/// - data: A chunk of `Data` to consume.
|
||||
/// - Throws: Can throw to indicate errors during data consumption.
|
||||
public typealias Consumer = (_ data: Data) throws -> Void
|
||||
/// A custom handler that receives a position and a size that can be used to provide data from an arbitrary source.
|
||||
/// - Parameters:
|
||||
/// - position: The current read position.
|
||||
/// - size: The size of the chunk to provide.
|
||||
/// - Returns: A chunk of `Data`.
|
||||
/// - Throws: Can throw to indicate errors in the data source.
|
||||
public typealias Provider = (_ position: Int, _ size: Int) throws -> Data
|
||||
|
||||
/// The lookup table used to calculate `CRC32` checksums.
|
||||
public let crcTable: [UInt32] = [
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
|
||||
0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
|
||||
0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
|
||||
0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
|
||||
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
|
||||
0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
||||
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
|
||||
0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
|
||||
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
|
||||
0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
|
||||
0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
|
||||
0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
|
||||
0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
|
||||
0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
|
||||
0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
|
||||
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
|
||||
0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
|
||||
0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
|
||||
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
|
||||
0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
|
||||
0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
|
||||
0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
|
||||
0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
|
||||
0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
|
||||
0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
|
||||
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
|
||||
0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
||||
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
|
||||
0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
|
||||
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
|
||||
0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
|
||||
0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
|
||||
0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
|
||||
0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
|
||||
0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
|
||||
0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
|
||||
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
|
||||
0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
|
||||
0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
|
||||
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
|
||||
0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
|
||||
0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
|
||||
0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
|
||||
0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
|
||||
0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
|
||||
0x2d02ef8d]
|
||||
|
||||
extension Data {
|
||||
enum CompressionError: Error {
|
||||
case invalidStream
|
||||
case corruptedData
|
||||
}
|
||||
|
||||
/// Calculate the `CRC32` checksum of the receiver.
|
||||
///
|
||||
/// - Parameter checksum: The starting seed.
|
||||
/// - Returns: The checksum calcualted from the bytes of the receiver and the starting seed.
|
||||
public func crc32(checksum: CRC32) -> CRC32 {
|
||||
// The typecast is necessary on 32-bit platforms because of
|
||||
// https://bugs.swift.org/browse/SR-1774
|
||||
let mask = 0xffffffff as UInt32
|
||||
let bufferSize = self.count/MemoryLayout<UInt8>.size
|
||||
var result = checksum ^ mask
|
||||
#if swift(>=5.0)
|
||||
crcTable.withUnsafeBufferPointer { crcTablePointer in
|
||||
self.withUnsafeBytes { bufferPointer in
|
||||
let bytePointer = bufferPointer.bindMemory(to: UInt8.self)
|
||||
for bufferIndex in 0..<bufferSize {
|
||||
let byte = bytePointer[bufferIndex]
|
||||
let index = Int((result ^ UInt32(byte)) & 0xff)
|
||||
result = (result >> 8) ^ crcTablePointer[index]
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
self.withUnsafeBytes { (bytes) in
|
||||
let bins = stride(from: 0, to: bufferSize, by: 256)
|
||||
for bin in bins {
|
||||
for binIndex in 0..<256 {
|
||||
let byteIndex = bin + binIndex
|
||||
guard byteIndex < bufferSize else { break }
|
||||
|
||||
let byte = bytes[byteIndex]
|
||||
let index = Int((result ^ UInt32(byte)) & 0xff)
|
||||
result = (result >> 8) ^ crcTable[index]
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return result ^ mask
|
||||
}
|
||||
|
||||
/// Compress the output of `provider` and pass it to `consumer`.
|
||||
/// - Parameters:
|
||||
/// - size: The uncompressed size of the data to be compressed.
|
||||
/// - bufferSize: The maximum size of the compression buffer.
|
||||
/// - provider: A closure that accepts a position and a chunk size. Returns a `Data` chunk.
|
||||
/// - consumer: A closure that processes the result of the compress operation.
|
||||
/// - Returns: The checksum of the processed content.
|
||||
public static func compress(size: Int, bufferSize: Int, provider: Provider, consumer: Consumer) throws -> CRC32 {
|
||||
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
|
||||
return try self.process(operation: COMPRESSION_STREAM_ENCODE, size: size, bufferSize: bufferSize,
|
||||
provider: provider, consumer: consumer)
|
||||
#else
|
||||
return try self.encode(size: size, bufferSize: bufferSize, provider: provider, consumer: consumer)
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Decompress the output of `provider` and pass it to `consumer`.
|
||||
/// - Parameters:
|
||||
/// - size: The compressed size of the data to be decompressed.
|
||||
/// - bufferSize: The maximum size of the decompression buffer.
|
||||
/// - skipCRC32: Optional flag to skip calculation of the CRC32 checksum to improve performance.
|
||||
/// - provider: A closure that accepts a position and a chunk size. Returns a `Data` chunk.
|
||||
/// - consumer: A closure that processes the result of the decompress operation.
|
||||
/// - Returns: The checksum of the processed content.
|
||||
public static func decompress(size: Int, bufferSize: Int, skipCRC32: Bool,
|
||||
provider: Provider, consumer: Consumer) throws -> CRC32 {
|
||||
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
|
||||
return try self.process(operation: COMPRESSION_STREAM_DECODE, size: size, bufferSize: bufferSize,
|
||||
skipCRC32: skipCRC32, provider: provider, consumer: consumer)
|
||||
#else
|
||||
return try self.decode(bufferSize: bufferSize, skipCRC32: skipCRC32, provider: provider, consumer: consumer)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Apple Platforms
|
||||
|
||||
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
|
||||
import Compression
|
||||
|
||||
extension Data {
|
||||
static func process(operation: compression_stream_operation, size: Int, bufferSize: Int, skipCRC32: Bool = false,
|
||||
provider: Provider, consumer: Consumer) throws -> CRC32 {
|
||||
var crc32 = CRC32(0)
|
||||
let destPointer = UnsafeMutablePointer<UInt8>.allocate(capacity: bufferSize)
|
||||
defer { destPointer.deallocate() }
|
||||
let streamPointer = UnsafeMutablePointer<compression_stream>.allocate(capacity: 1)
|
||||
defer { streamPointer.deallocate() }
|
||||
var stream = streamPointer.pointee
|
||||
var status = compression_stream_init(&stream, operation, COMPRESSION_ZLIB)
|
||||
guard status != COMPRESSION_STATUS_ERROR else { throw CompressionError.invalidStream }
|
||||
defer { compression_stream_destroy(&stream) }
|
||||
stream.src_size = 0
|
||||
stream.dst_ptr = destPointer
|
||||
stream.dst_size = bufferSize
|
||||
var position = 0
|
||||
var sourceData: Data?
|
||||
repeat {
|
||||
if stream.src_size == 0 {
|
||||
do {
|
||||
sourceData = try provider(position, Swift.min((size - position), bufferSize))
|
||||
if let sourceData = sourceData {
|
||||
position += sourceData.count
|
||||
stream.src_size = sourceData.count
|
||||
}
|
||||
} catch { throw error }
|
||||
}
|
||||
if let sourceData = sourceData {
|
||||
sourceData.withUnsafeBytes { (rawBufferPointer) in
|
||||
if let baseAddress = rawBufferPointer.baseAddress {
|
||||
let pointer = baseAddress.assumingMemoryBound(to: UInt8.self)
|
||||
stream.src_ptr = pointer.advanced(by: sourceData.count - stream.src_size)
|
||||
let flags = sourceData.count < bufferSize ? Int32(COMPRESSION_STREAM_FINALIZE.rawValue) : 0
|
||||
status = compression_stream_process(&stream, flags)
|
||||
}
|
||||
}
|
||||
if operation == COMPRESSION_STREAM_ENCODE && !skipCRC32 { crc32 = sourceData.crc32(checksum: crc32) }
|
||||
}
|
||||
switch status {
|
||||
case COMPRESSION_STATUS_OK, COMPRESSION_STATUS_END:
|
||||
let outputData = Data(bytesNoCopy: destPointer, count: bufferSize - stream.dst_size, deallocator: .none)
|
||||
try consumer(outputData)
|
||||
if operation == COMPRESSION_STREAM_DECODE && !skipCRC32 { crc32 = outputData.crc32(checksum: crc32) }
|
||||
stream.dst_ptr = destPointer
|
||||
stream.dst_size = bufferSize
|
||||
default: throw CompressionError.corruptedData
|
||||
}
|
||||
} while status == COMPRESSION_STATUS_OK
|
||||
return crc32
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Linux
|
||||
|
||||
#else
|
||||
import CZlib
|
||||
|
||||
extension Data {
|
||||
static func encode(size: Int, bufferSize: Int, provider: Provider, consumer: Consumer) throws -> CRC32 {
|
||||
var stream = z_stream()
|
||||
let streamSize = Int32(MemoryLayout<z_stream>.size)
|
||||
var result = deflateInit2_(&stream, Z_DEFAULT_COMPRESSION,
|
||||
Z_DEFLATED, -MAX_WBITS, 9, Z_DEFAULT_STRATEGY, ZLIB_VERSION, streamSize)
|
||||
defer { deflateEnd(&stream) }
|
||||
guard result == Z_OK else { throw CompressionError.invalidStream }
|
||||
var flush = Z_NO_FLUSH
|
||||
var position = 0
|
||||
var zipCRC32 = CRC32(0)
|
||||
repeat {
|
||||
let readSize = Swift.min((size - position), bufferSize)
|
||||
var inputChunk = try provider(position, readSize)
|
||||
zipCRC32 = inputChunk.crc32(checksum: zipCRC32)
|
||||
stream.avail_in = UInt32(inputChunk.count)
|
||||
try inputChunk.withUnsafeMutableBytes { (rawBufferPointer) in
|
||||
if let baseAddress = rawBufferPointer.baseAddress {
|
||||
let pointer = baseAddress.assumingMemoryBound(to: UInt8.self)
|
||||
stream.next_in = pointer
|
||||
flush = position + bufferSize >= size ? Z_FINISH : Z_NO_FLUSH
|
||||
} else if rawBufferPointer.count > 0 {
|
||||
throw CompressionError.corruptedData
|
||||
} else {
|
||||
stream.next_in = nil
|
||||
flush = Z_FINISH
|
||||
}
|
||||
var outputChunk = Data(count: bufferSize)
|
||||
repeat {
|
||||
stream.avail_out = UInt32(bufferSize)
|
||||
try outputChunk.withUnsafeMutableBytes { (rawBufferPointer) in
|
||||
guard let baseAddress = rawBufferPointer.baseAddress, rawBufferPointer.count > 0 else {
|
||||
throw CompressionError.corruptedData
|
||||
}
|
||||
let pointer = baseAddress.assumingMemoryBound(to: UInt8.self)
|
||||
stream.next_out = pointer
|
||||
result = deflate(&stream, flush)
|
||||
}
|
||||
guard result >= Z_OK else { throw CompressionError.corruptedData }
|
||||
|
||||
outputChunk.count = bufferSize - Int(stream.avail_out)
|
||||
try consumer(outputChunk)
|
||||
} while stream.avail_out == 0
|
||||
}
|
||||
position += readSize
|
||||
} while flush != Z_FINISH
|
||||
return zipCRC32
|
||||
}
|
||||
|
||||
static func decode(bufferSize: Int, skipCRC32: Bool, provider: Provider, consumer: Consumer) throws -> CRC32 {
|
||||
var stream = z_stream()
|
||||
let streamSize = Int32(MemoryLayout<z_stream>.size)
|
||||
var result = inflateInit2_(&stream, -MAX_WBITS, ZLIB_VERSION, streamSize)
|
||||
defer { inflateEnd(&stream) }
|
||||
guard result == Z_OK else { throw CompressionError.invalidStream }
|
||||
var unzipCRC32 = CRC32(0)
|
||||
var position = 0
|
||||
repeat {
|
||||
stream.avail_in = UInt32(bufferSize)
|
||||
var chunk = try provider(position, bufferSize)
|
||||
position += chunk.count
|
||||
try chunk.withUnsafeMutableBytes { (rawBufferPointer) in
|
||||
if let baseAddress = rawBufferPointer.baseAddress, rawBufferPointer.count > 0 {
|
||||
let pointer = baseAddress.assumingMemoryBound(to: UInt8.self)
|
||||
stream.next_in = pointer
|
||||
repeat {
|
||||
var outputData = Data(count: bufferSize)
|
||||
stream.avail_out = UInt32(bufferSize)
|
||||
try outputData.withUnsafeMutableBytes { (rawBufferPointer) in
|
||||
if let baseAddress = rawBufferPointer.baseAddress, rawBufferPointer.count > 0 {
|
||||
let pointer = baseAddress.assumingMemoryBound(to: UInt8.self)
|
||||
stream.next_out = pointer
|
||||
} else {
|
||||
throw CompressionError.corruptedData
|
||||
}
|
||||
result = inflate(&stream, Z_NO_FLUSH)
|
||||
guard result != Z_NEED_DICT &&
|
||||
result != Z_DATA_ERROR &&
|
||||
result != Z_MEM_ERROR else {
|
||||
throw CompressionError.corruptedData
|
||||
}
|
||||
}
|
||||
let remainingLength = UInt32(bufferSize) - stream.avail_out
|
||||
outputData.count = Int(remainingLength)
|
||||
try consumer(outputData)
|
||||
if !skipCRC32 { unzipCRC32 = outputData.crc32(checksum: unzipCRC32) }
|
||||
} while stream.avail_out == 0
|
||||
}
|
||||
}
|
||||
} while result != Z_STREAM_END
|
||||
return unzipCRC32
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !swift(>=5.0)
|
||||
|
||||
// Since Swift 5.0, `Data.withUnsafeBytes()` passes an `UnsafeRawBufferPointer` instead of an `UnsafePointer<UInt8>`
|
||||
// into `body`.
|
||||
// We provide a compatible method for targets that use Swift 4.x so that we can use the new version
|
||||
// across all language versions.
|
||||
|
||||
internal extension Data {
|
||||
func withUnsafeBytes<T>(_ body: (UnsafeRawBufferPointer) throws -> T) rethrows -> T {
|
||||
let count = self.count
|
||||
return try withUnsafeBytes { (pointer: UnsafePointer<UInt8>) throws -> T in
|
||||
try body(UnsafeRawBufferPointer(start: pointer, count: count))
|
||||
}
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
|
||||
#else
|
||||
mutating func withUnsafeMutableBytes<T>(_ body: (UnsafeMutableRawBufferPointer) throws -> T) rethrows -> T {
|
||||
let count = self.count
|
||||
guard count > 0 else {
|
||||
return try body(UnsafeMutableRawBufferPointer(start: nil, count: count))
|
||||
}
|
||||
return try withUnsafeMutableBytes { (pointer: UnsafeMutablePointer<UInt8>) throws -> T in
|
||||
try body(UnsafeMutableRawBufferPointer(start: pointer, count: count))
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
@ -1,103 +0,0 @@
|
||||
//
|
||||
// Data+Serialization.swift
|
||||
// ZIPFoundation
|
||||
//
|
||||
// Copyright © 2017-2020 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
protocol DataSerializable {
|
||||
static var size: Int { get }
|
||||
init?(data: Data, additionalDataProvider: (Int) throws -> Data)
|
||||
var data: Data { get }
|
||||
}
|
||||
|
||||
extension Data {
|
||||
enum DataError: Error {
|
||||
case unreadableFile
|
||||
case unwritableFile
|
||||
}
|
||||
|
||||
func scanValue<T>(start: Int) -> T {
|
||||
let subdata = self.subdata(in: start..<start+MemoryLayout<T>.size)
|
||||
#if swift(>=5.0)
|
||||
return subdata.withUnsafeBytes { $0.load(as: T.self) }
|
||||
#else
|
||||
return subdata.withUnsafeBytes { $0.pointee }
|
||||
#endif
|
||||
}
|
||||
|
||||
static func readStruct<T>(from file: UnsafeMutablePointer<FILE>, at offset: Int) -> T? where T: DataSerializable {
|
||||
fseek(file, offset, SEEK_SET)
|
||||
guard let data = try? self.readChunk(of: T.size, from: file) else {
|
||||
return nil
|
||||
}
|
||||
let structure = T(data: data, additionalDataProvider: { (additionalDataSize) -> Data in
|
||||
return try self.readChunk(of: additionalDataSize, from: file)
|
||||
})
|
||||
return structure
|
||||
}
|
||||
|
||||
static func consumePart(of size: Int, chunkSize: Int, skipCRC32: Bool = false,
|
||||
provider: Provider, consumer: Consumer) throws -> CRC32 {
|
||||
var checksum = CRC32(0)
|
||||
guard size > 0 else {
|
||||
try consumer(Data())
|
||||
return checksum
|
||||
}
|
||||
|
||||
let readInOneChunk = (size < chunkSize)
|
||||
var chunkSize = readInOneChunk ? size : chunkSize
|
||||
var bytesRead = 0
|
||||
while bytesRead < size {
|
||||
let remainingSize = size - bytesRead
|
||||
chunkSize = remainingSize < chunkSize ? remainingSize : chunkSize
|
||||
let data = try provider(bytesRead, chunkSize)
|
||||
try consumer(data)
|
||||
if !skipCRC32 {
|
||||
checksum = data.crc32(checksum: checksum)
|
||||
}
|
||||
bytesRead += chunkSize
|
||||
}
|
||||
return checksum
|
||||
}
|
||||
|
||||
static func readChunk(of size: Int, from file: UnsafeMutablePointer<FILE>) throws -> Data {
|
||||
let alignment = MemoryLayout<UInt>.alignment
|
||||
#if swift(>=4.1)
|
||||
let bytes = UnsafeMutableRawPointer.allocate(byteCount: size, alignment: alignment)
|
||||
#else
|
||||
let bytes = UnsafeMutableRawPointer.allocate(bytes: size, alignedTo: alignment)
|
||||
#endif
|
||||
let bytesRead = fread(bytes, 1, size, file)
|
||||
let error = ferror(file)
|
||||
if error > 0 {
|
||||
throw DataError.unreadableFile
|
||||
}
|
||||
#if swift(>=4.1)
|
||||
return Data(bytesNoCopy: bytes, count: bytesRead, deallocator: .custom({ buf, _ in buf.deallocate() }))
|
||||
#else
|
||||
let deallocator = Deallocator.custom({ buf, _ in buf.deallocate(bytes: size, alignedTo: 1) })
|
||||
return Data(bytesNoCopy: bytes, count: bytesRead, deallocator: deallocator)
|
||||
#endif
|
||||
}
|
||||
|
||||
static func write(chunk: Data, to file: UnsafeMutablePointer<FILE>) throws -> Int {
|
||||
var sizeWritten = 0
|
||||
chunk.withUnsafeBytes { (rawBufferPointer) in
|
||||
if let baseAddress = rawBufferPointer.baseAddress, rawBufferPointer.count > 0 {
|
||||
let pointer = baseAddress.assumingMemoryBound(to: UInt8.self)
|
||||
sizeWritten = fwrite(pointer, 1, chunk.count, file)
|
||||
}
|
||||
}
|
||||
let error = ferror(file)
|
||||
if error > 0 {
|
||||
throw DataError.unwritableFile
|
||||
}
|
||||
return sizeWritten
|
||||
}
|
||||
}
|
400
third-party/ZIPFoundation/Sources/Entry.swift
vendored
400
third-party/ZIPFoundation/Sources/Entry.swift
vendored
@ -1,400 +0,0 @@
|
||||
//
|
||||
// Entry.swift
|
||||
// ZIPFoundation
|
||||
//
|
||||
// Copyright © 2017-2020 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreFoundation
|
||||
|
||||
/// A value that represents a file, a directory or a symbolic link within a ZIP `Archive`.
|
||||
///
|
||||
/// You can retrieve instances of `Entry` from an `Archive` via subscripting or iteration.
|
||||
/// Entries are identified by their `path`.
|
||||
public struct Entry: Equatable {
|
||||
/// The type of an `Entry` in a ZIP `Archive`.
|
||||
public enum EntryType: Int {
|
||||
/// Indicates a regular file.
|
||||
case file
|
||||
/// Indicates a directory.
|
||||
case directory
|
||||
/// Indicates a symbolic link.
|
||||
case symlink
|
||||
|
||||
init(mode: mode_t) {
|
||||
switch mode & S_IFMT {
|
||||
case S_IFDIR:
|
||||
self = .directory
|
||||
case S_IFLNK:
|
||||
self = .symlink
|
||||
default:
|
||||
self = .file
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum OSType: UInt {
|
||||
case msdos = 0
|
||||
case unix = 3
|
||||
case osx = 19
|
||||
case unused = 20
|
||||
}
|
||||
|
||||
struct LocalFileHeader: DataSerializable {
|
||||
let localFileHeaderSignature = UInt32(localFileHeaderStructSignature)
|
||||
let versionNeededToExtract: UInt16
|
||||
let generalPurposeBitFlag: UInt16
|
||||
let compressionMethod: UInt16
|
||||
let lastModFileTime: UInt16
|
||||
let lastModFileDate: UInt16
|
||||
let crc32: UInt32
|
||||
let compressedSize: UInt32
|
||||
let uncompressedSize: UInt32
|
||||
let fileNameLength: UInt16
|
||||
let extraFieldLength: UInt16
|
||||
static let size = 30
|
||||
let fileNameData: Data
|
||||
let extraFieldData: Data
|
||||
}
|
||||
|
||||
struct DataDescriptor: DataSerializable {
|
||||
let data: Data
|
||||
let dataDescriptorSignature = UInt32(dataDescriptorStructSignature)
|
||||
let crc32: UInt32
|
||||
let compressedSize: UInt32
|
||||
let uncompressedSize: UInt32
|
||||
static let size = 16
|
||||
}
|
||||
|
||||
struct CentralDirectoryStructure: DataSerializable {
|
||||
let centralDirectorySignature = UInt32(centralDirectoryStructSignature)
|
||||
let versionMadeBy: UInt16
|
||||
let versionNeededToExtract: UInt16
|
||||
let generalPurposeBitFlag: UInt16
|
||||
let compressionMethod: UInt16
|
||||
let lastModFileTime: UInt16
|
||||
let lastModFileDate: UInt16
|
||||
let crc32: UInt32
|
||||
let compressedSize: UInt32
|
||||
let uncompressedSize: UInt32
|
||||
let fileNameLength: UInt16
|
||||
let extraFieldLength: UInt16
|
||||
let fileCommentLength: UInt16
|
||||
let diskNumberStart: UInt16
|
||||
let internalFileAttributes: UInt16
|
||||
let externalFileAttributes: UInt32
|
||||
let relativeOffsetOfLocalHeader: UInt32
|
||||
static let size = 46
|
||||
let fileNameData: Data
|
||||
let extraFieldData: Data
|
||||
let fileCommentData: Data
|
||||
var usesDataDescriptor: Bool { return (self.generalPurposeBitFlag & (1 << 3 )) != 0 }
|
||||
var usesUTF8PathEncoding: Bool { return (self.generalPurposeBitFlag & (1 << 11 )) != 0 }
|
||||
var isEncrypted: Bool { return (self.generalPurposeBitFlag & (1 << 0)) != 0 }
|
||||
var isZIP64: Bool { return self.versionNeededToExtract >= 45 }
|
||||
}
|
||||
/// Returns the `path` of the receiver within a ZIP `Archive` using a given encoding.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - encoding: `String.Encoding`
|
||||
public func path(using encoding: String.Encoding) -> String {
|
||||
return String(data: self.centralDirectoryStructure.fileNameData, encoding: encoding) ?? ""
|
||||
}
|
||||
/// The `path` of the receiver within a ZIP `Archive`.
|
||||
public var path: String {
|
||||
let dosLatinUS = 0x400
|
||||
let dosLatinUSEncoding = CFStringEncoding(dosLatinUS)
|
||||
let dosLatinUSStringEncoding = CFStringConvertEncodingToNSStringEncoding(dosLatinUSEncoding)
|
||||
let codepage437 = String.Encoding(rawValue: dosLatinUSStringEncoding)
|
||||
let encoding = self.centralDirectoryStructure.usesUTF8PathEncoding ? .utf8 : codepage437
|
||||
return self.path(using: encoding)
|
||||
}
|
||||
/// The file attributes of the receiver as key/value pairs.
|
||||
///
|
||||
/// Contains the modification date and file permissions.
|
||||
public var fileAttributes: [FileAttributeKey: Any] {
|
||||
return FileManager.attributes(from: self)
|
||||
}
|
||||
/// The `CRC32` checksum of the receiver.
|
||||
///
|
||||
/// - Note: Always returns `0` for entries of type `EntryType.directory`.
|
||||
public var checksum: CRC32 {
|
||||
var checksum = self.centralDirectoryStructure.crc32
|
||||
if self.centralDirectoryStructure.usesDataDescriptor {
|
||||
guard let dataDescriptor = self.dataDescriptor else { return 0 }
|
||||
checksum = dataDescriptor.crc32
|
||||
}
|
||||
return checksum
|
||||
}
|
||||
/// The `EntryType` of the receiver.
|
||||
public var type: EntryType {
|
||||
// OS Type is stored in the upper byte of versionMadeBy
|
||||
let osTypeRaw = self.centralDirectoryStructure.versionMadeBy >> 8
|
||||
let osType = OSType(rawValue: UInt(osTypeRaw)) ?? .unused
|
||||
var isDirectory = self.path.hasSuffix("/")
|
||||
switch osType {
|
||||
case .unix, .osx:
|
||||
let mode = mode_t(self.centralDirectoryStructure.externalFileAttributes >> 16) & S_IFMT
|
||||
switch mode {
|
||||
case S_IFREG:
|
||||
return .file
|
||||
case S_IFDIR:
|
||||
return .directory
|
||||
case S_IFLNK:
|
||||
return .symlink
|
||||
default:
|
||||
return isDirectory ? .directory : .file
|
||||
}
|
||||
case .msdos:
|
||||
isDirectory = isDirectory || ((centralDirectoryStructure.externalFileAttributes >> 4) == 0x01)
|
||||
fallthrough // For all other OSes we can only guess based on the directory suffix char
|
||||
default: return isDirectory ? .directory : .file
|
||||
}
|
||||
}
|
||||
/// The size of the receiver's compressed data.
|
||||
public var compressedSize: Int {
|
||||
return Int(dataDescriptor?.compressedSize ?? localFileHeader.compressedSize)
|
||||
}
|
||||
/// The size of the receiver's uncompressed data.
|
||||
public var uncompressedSize: Int {
|
||||
return Int(dataDescriptor?.uncompressedSize ?? localFileHeader.uncompressedSize)
|
||||
}
|
||||
/// The combined size of the local header, the data and the optional data descriptor.
|
||||
var localSize: Int {
|
||||
let localFileHeader = self.localFileHeader
|
||||
var extraDataLength = Int(localFileHeader.fileNameLength)
|
||||
extraDataLength += Int(localFileHeader.extraFieldLength)
|
||||
var size = LocalFileHeader.size + extraDataLength
|
||||
let isCompressed = localFileHeader.compressionMethod != CompressionMethod.none.rawValue
|
||||
size += isCompressed ? self.compressedSize : self.uncompressedSize
|
||||
size += self.dataDescriptor != nil ? DataDescriptor.size : 0
|
||||
return size
|
||||
}
|
||||
var dataOffset: Int {
|
||||
var dataOffset = Int(self.centralDirectoryStructure.relativeOffsetOfLocalHeader)
|
||||
dataOffset += LocalFileHeader.size
|
||||
dataOffset += Int(self.localFileHeader.fileNameLength)
|
||||
dataOffset += Int(self.localFileHeader.extraFieldLength)
|
||||
return dataOffset
|
||||
}
|
||||
let centralDirectoryStructure: CentralDirectoryStructure
|
||||
let localFileHeader: LocalFileHeader
|
||||
let dataDescriptor: DataDescriptor?
|
||||
|
||||
public static func == (lhs: Entry, rhs: Entry) -> Bool {
|
||||
return lhs.path == rhs.path
|
||||
&& lhs.localFileHeader.crc32 == rhs.localFileHeader.crc32
|
||||
&& lhs.centralDirectoryStructure.relativeOffsetOfLocalHeader
|
||||
== rhs.centralDirectoryStructure.relativeOffsetOfLocalHeader
|
||||
}
|
||||
|
||||
init?(centralDirectoryStructure: CentralDirectoryStructure,
|
||||
localFileHeader: LocalFileHeader,
|
||||
dataDescriptor: DataDescriptor?) {
|
||||
// We currently don't support ZIP64 or encrypted archives
|
||||
guard !centralDirectoryStructure.isZIP64 else { return nil }
|
||||
guard !centralDirectoryStructure.isEncrypted else { return nil }
|
||||
self.centralDirectoryStructure = centralDirectoryStructure
|
||||
self.localFileHeader = localFileHeader
|
||||
self.dataDescriptor = dataDescriptor
|
||||
}
|
||||
}
|
||||
|
||||
extension Entry.LocalFileHeader {
|
||||
var data: Data {
|
||||
var localFileHeaderSignature = self.localFileHeaderSignature
|
||||
var versionNeededToExtract = self.versionNeededToExtract
|
||||
var generalPurposeBitFlag = self.generalPurposeBitFlag
|
||||
var compressionMethod = self.compressionMethod
|
||||
var lastModFileTime = self.lastModFileTime
|
||||
var lastModFileDate = self.lastModFileDate
|
||||
var crc32 = self.crc32
|
||||
var compressedSize = self.compressedSize
|
||||
var uncompressedSize = self.uncompressedSize
|
||||
var fileNameLength = self.fileNameLength
|
||||
var extraFieldLength = self.extraFieldLength
|
||||
var data = Data()
|
||||
withUnsafePointer(to: &localFileHeaderSignature, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &versionNeededToExtract, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &generalPurposeBitFlag, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &compressionMethod, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &lastModFileTime, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &lastModFileDate, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &crc32, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &compressedSize, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &uncompressedSize, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &fileNameLength, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &extraFieldLength, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
data.append(self.fileNameData)
|
||||
data.append(self.extraFieldData)
|
||||
return data
|
||||
}
|
||||
|
||||
init?(data: Data, additionalDataProvider provider: (Int) throws -> Data) {
|
||||
guard data.count == Entry.LocalFileHeader.size else { return nil }
|
||||
guard data.scanValue(start: 0) == localFileHeaderSignature else { return nil }
|
||||
self.versionNeededToExtract = data.scanValue(start: 4)
|
||||
self.generalPurposeBitFlag = data.scanValue(start: 6)
|
||||
self.compressionMethod = data.scanValue(start: 8)
|
||||
self.lastModFileTime = data.scanValue(start: 10)
|
||||
self.lastModFileDate = data.scanValue(start: 12)
|
||||
self.crc32 = data.scanValue(start: 14)
|
||||
self.compressedSize = data.scanValue(start: 18)
|
||||
self.uncompressedSize = data.scanValue(start: 22)
|
||||
self.fileNameLength = data.scanValue(start: 26)
|
||||
self.extraFieldLength = data.scanValue(start: 28)
|
||||
let additionalDataLength = Int(self.fileNameLength) + Int(self.extraFieldLength)
|
||||
guard let additionalData = try? provider(additionalDataLength) else { return nil }
|
||||
guard additionalData.count == additionalDataLength else { return nil }
|
||||
var subRangeStart = 0
|
||||
var subRangeEnd = Int(self.fileNameLength)
|
||||
self.fileNameData = additionalData.subdata(in: subRangeStart..<subRangeEnd)
|
||||
subRangeStart += Int(self.fileNameLength)
|
||||
subRangeEnd = subRangeStart + Int(self.extraFieldLength)
|
||||
self.extraFieldData = additionalData.subdata(in: subRangeStart..<subRangeEnd)
|
||||
}
|
||||
}
|
||||
|
||||
extension Entry.CentralDirectoryStructure {
|
||||
var data: Data {
|
||||
var centralDirectorySignature = self.centralDirectorySignature
|
||||
var versionMadeBy = self.versionMadeBy
|
||||
var versionNeededToExtract = self.versionNeededToExtract
|
||||
var generalPurposeBitFlag = self.generalPurposeBitFlag
|
||||
var compressionMethod = self.compressionMethod
|
||||
var lastModFileTime = self.lastModFileTime
|
||||
var lastModFileDate = self.lastModFileDate
|
||||
var crc32 = self.crc32
|
||||
var compressedSize = self.compressedSize
|
||||
var uncompressedSize = self.uncompressedSize
|
||||
var fileNameLength = self.fileNameLength
|
||||
var extraFieldLength = self.extraFieldLength
|
||||
var fileCommentLength = self.fileCommentLength
|
||||
var diskNumberStart = self.diskNumberStart
|
||||
var internalFileAttributes = self.internalFileAttributes
|
||||
var externalFileAttributes = self.externalFileAttributes
|
||||
var relativeOffsetOfLocalHeader = self.relativeOffsetOfLocalHeader
|
||||
var data = Data()
|
||||
withUnsafePointer(to: ¢ralDirectorySignature, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &versionMadeBy, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &versionNeededToExtract, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &generalPurposeBitFlag, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &compressionMethod, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &lastModFileTime, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &lastModFileDate, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &crc32, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &compressedSize, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &uncompressedSize, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &fileNameLength, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &extraFieldLength, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &fileCommentLength, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &diskNumberStart, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &internalFileAttributes, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &externalFileAttributes, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
withUnsafePointer(to: &relativeOffsetOfLocalHeader, { data.append(UnsafeBufferPointer(start: $0, count: 1))})
|
||||
data.append(self.fileNameData)
|
||||
data.append(self.extraFieldData)
|
||||
data.append(self.fileCommentData)
|
||||
return data
|
||||
}
|
||||
|
||||
init?(data: Data, additionalDataProvider provider: (Int) throws -> Data) {
|
||||
guard data.count == Entry.CentralDirectoryStructure.size else { return nil }
|
||||
guard data.scanValue(start: 0) == centralDirectorySignature else { return nil }
|
||||
self.versionMadeBy = data.scanValue(start: 4)
|
||||
self.versionNeededToExtract = data.scanValue(start: 6)
|
||||
self.generalPurposeBitFlag = data.scanValue(start: 8)
|
||||
self.compressionMethod = data.scanValue(start: 10)
|
||||
self.lastModFileTime = data.scanValue(start: 12)
|
||||
self.lastModFileDate = data.scanValue(start: 14)
|
||||
self.crc32 = data.scanValue(start: 16)
|
||||
self.compressedSize = data.scanValue(start: 20)
|
||||
self.uncompressedSize = data.scanValue(start: 24)
|
||||
self.fileNameLength = data.scanValue(start: 28)
|
||||
self.extraFieldLength = data.scanValue(start: 30)
|
||||
self.fileCommentLength = data.scanValue(start: 32)
|
||||
self.diskNumberStart = data.scanValue(start: 34)
|
||||
self.internalFileAttributes = data.scanValue(start: 36)
|
||||
self.externalFileAttributes = data.scanValue(start: 38)
|
||||
self.relativeOffsetOfLocalHeader = data.scanValue(start: 42)
|
||||
let additionalDataLength = Int(self.fileNameLength) + Int(self.extraFieldLength) + Int(self.fileCommentLength)
|
||||
guard let additionalData = try? provider(additionalDataLength) else { return nil }
|
||||
guard additionalData.count == additionalDataLength else { return nil }
|
||||
var subRangeStart = 0
|
||||
var subRangeEnd = Int(self.fileNameLength)
|
||||
self.fileNameData = additionalData.subdata(in: subRangeStart..<subRangeEnd)
|
||||
subRangeStart += Int(self.fileNameLength)
|
||||
subRangeEnd = subRangeStart + Int(self.extraFieldLength)
|
||||
self.extraFieldData = additionalData.subdata(in: subRangeStart..<subRangeEnd)
|
||||
subRangeStart += Int(self.extraFieldLength)
|
||||
subRangeEnd = subRangeStart + Int(self.fileCommentLength)
|
||||
self.fileCommentData = additionalData.subdata(in: subRangeStart..<subRangeEnd)
|
||||
}
|
||||
|
||||
init(localFileHeader: Entry.LocalFileHeader, fileAttributes: UInt32, relativeOffset: UInt32) {
|
||||
versionMadeBy = UInt16(789)
|
||||
versionNeededToExtract = localFileHeader.versionNeededToExtract
|
||||
generalPurposeBitFlag = localFileHeader.generalPurposeBitFlag
|
||||
compressionMethod = localFileHeader.compressionMethod
|
||||
lastModFileTime = localFileHeader.lastModFileTime
|
||||
lastModFileDate = localFileHeader.lastModFileDate
|
||||
crc32 = localFileHeader.crc32
|
||||
compressedSize = localFileHeader.compressedSize
|
||||
uncompressedSize = localFileHeader.uncompressedSize
|
||||
fileNameLength = localFileHeader.fileNameLength
|
||||
extraFieldLength = UInt16(0)
|
||||
fileCommentLength = UInt16(0)
|
||||
diskNumberStart = UInt16(0)
|
||||
internalFileAttributes = UInt16(0)
|
||||
externalFileAttributes = fileAttributes
|
||||
relativeOffsetOfLocalHeader = relativeOffset
|
||||
fileNameData = localFileHeader.fileNameData
|
||||
extraFieldData = Data()
|
||||
fileCommentData = Data()
|
||||
}
|
||||
|
||||
init(centralDirectoryStructure: Entry.CentralDirectoryStructure, offset: UInt32) {
|
||||
let relativeOffset = centralDirectoryStructure.relativeOffsetOfLocalHeader - offset
|
||||
relativeOffsetOfLocalHeader = relativeOffset
|
||||
versionMadeBy = centralDirectoryStructure.versionMadeBy
|
||||
versionNeededToExtract = centralDirectoryStructure.versionNeededToExtract
|
||||
generalPurposeBitFlag = centralDirectoryStructure.generalPurposeBitFlag
|
||||
compressionMethod = centralDirectoryStructure.compressionMethod
|
||||
lastModFileTime = centralDirectoryStructure.lastModFileTime
|
||||
lastModFileDate = centralDirectoryStructure.lastModFileDate
|
||||
crc32 = centralDirectoryStructure.crc32
|
||||
compressedSize = centralDirectoryStructure.compressedSize
|
||||
uncompressedSize = centralDirectoryStructure.uncompressedSize
|
||||
fileNameLength = centralDirectoryStructure.fileNameLength
|
||||
extraFieldLength = centralDirectoryStructure.extraFieldLength
|
||||
fileCommentLength = centralDirectoryStructure.fileCommentLength
|
||||
diskNumberStart = centralDirectoryStructure.diskNumberStart
|
||||
internalFileAttributes = centralDirectoryStructure.internalFileAttributes
|
||||
externalFileAttributes = centralDirectoryStructure.externalFileAttributes
|
||||
fileNameData = centralDirectoryStructure.fileNameData
|
||||
extraFieldData = centralDirectoryStructure.extraFieldData
|
||||
fileCommentData = centralDirectoryStructure.fileCommentData
|
||||
}
|
||||
}
|
||||
|
||||
extension Entry.DataDescriptor {
|
||||
init?(data: Data, additionalDataProvider provider: (Int) throws -> Data) {
|
||||
guard data.count == Entry.DataDescriptor.size else { return nil }
|
||||
let signature: UInt32 = data.scanValue(start: 0)
|
||||
// The DataDescriptor signature is not mandatory so we have to re-arrange the input data if it is missing.
|
||||
var readOffset = 0
|
||||
if signature == self.dataDescriptorSignature { readOffset = 4 }
|
||||
self.crc32 = data.scanValue(start: readOffset + 0)
|
||||
self.compressedSize = data.scanValue(start: readOffset + 4)
|
||||
self.uncompressedSize = data.scanValue(start: readOffset + 8)
|
||||
// Our add(_ entry:) methods always maintain compressed & uncompressed
|
||||
// sizes and so we don't need a data descriptor for newly added entries.
|
||||
// Data descriptors of already existing entries are manually preserved
|
||||
// when copying those entries to the tempArchive during remove(_ entry:).
|
||||
self.data = Data()
|
||||
}
|
||||
}
|
@ -1,326 +0,0 @@
|
||||
//
|
||||
// FileManager+ZIP.swift
|
||||
// ZIPFoundation
|
||||
//
|
||||
// Copyright © 2017-2020 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension FileManager {
|
||||
typealias CentralDirectoryStructure = Entry.CentralDirectoryStructure
|
||||
|
||||
/// Zips the file or direcory contents at the specified source URL to the destination URL.
|
||||
///
|
||||
/// If the item at the source URL is a directory, the directory itself will be
|
||||
/// represented within the ZIP `Archive`. Calling this method with a directory URL
|
||||
/// `file:///path/directory/` will create an archive with a `directory/` entry at the root level.
|
||||
/// You can override this behavior by passing `false` for `shouldKeepParent`. In that case, the contents
|
||||
/// of the source directory will be placed at the root of the archive.
|
||||
/// - Parameters:
|
||||
/// - sourceURL: The file URL pointing to an existing file or directory.
|
||||
/// - destinationURL: The file URL that identifies the destination of the zip operation.
|
||||
/// - shouldKeepParent: Indicates that the directory name of a source item should be used as root element
|
||||
/// within the archive. Default is `true`.
|
||||
/// - compressionMethod: Indicates the `CompressionMethod` that should be applied.
|
||||
/// By default, `zipItem` will create uncompressed archives.
|
||||
/// - progress: A progress object that can be used to track or cancel the zip operation.
|
||||
/// - Throws: Throws an error if the source item does not exist or the destination URL is not writable.
|
||||
public func zipItem(at sourceURL: URL, to destinationURL: URL,
|
||||
shouldKeepParent: Bool = true, compressionMethod: CompressionMethod = .none,
|
||||
progress: Progress? = nil) throws {
|
||||
let fileManager = FileManager()
|
||||
guard fileManager.itemExists(at: sourceURL) else {
|
||||
throw CocoaError(.fileReadNoSuchFile, userInfo: [NSFilePathErrorKey: sourceURL.path])
|
||||
}
|
||||
guard !fileManager.itemExists(at: destinationURL) else {
|
||||
throw CocoaError(.fileWriteFileExists, userInfo: [NSFilePathErrorKey: destinationURL.path])
|
||||
}
|
||||
guard let archive = Archive(url: destinationURL, accessMode: .create) else {
|
||||
throw Archive.ArchiveError.unwritableArchive
|
||||
}
|
||||
let isDirectory = try FileManager.typeForItem(at: sourceURL) == .directory
|
||||
if isDirectory {
|
||||
let subPaths = try self.subpathsOfDirectory(atPath: sourceURL.path)
|
||||
var totalUnitCount = Int64(0)
|
||||
if let progress = progress {
|
||||
totalUnitCount = subPaths.reduce(Int64(0), {
|
||||
let itemURL = sourceURL.appendingPathComponent($1)
|
||||
let itemSize = archive.totalUnitCountForAddingItem(at: itemURL)
|
||||
return $0 + itemSize
|
||||
})
|
||||
progress.totalUnitCount = totalUnitCount
|
||||
}
|
||||
|
||||
// If the caller wants to keep the parent directory, we use the lastPathComponent of the source URL
|
||||
// as common base for all entries (similar to macOS' Archive Utility.app)
|
||||
let directoryPrefix = sourceURL.lastPathComponent
|
||||
for entryPath in subPaths {
|
||||
let finalEntryPath = shouldKeepParent ? directoryPrefix + "/" + entryPath : entryPath
|
||||
let finalBaseURL = shouldKeepParent ? sourceURL.deletingLastPathComponent() : sourceURL
|
||||
if let progress = progress {
|
||||
let itemURL = sourceURL.appendingPathComponent(entryPath)
|
||||
let entryProgress = archive.makeProgressForAddingItem(at: itemURL)
|
||||
progress.addChild(entryProgress, withPendingUnitCount: entryProgress.totalUnitCount)
|
||||
try archive.addEntry(with: finalEntryPath, relativeTo: finalBaseURL,
|
||||
compressionMethod: compressionMethod, progress: entryProgress)
|
||||
} else {
|
||||
try archive.addEntry(with: finalEntryPath, relativeTo: finalBaseURL,
|
||||
compressionMethod: compressionMethod)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
progress?.totalUnitCount = archive.totalUnitCountForAddingItem(at: sourceURL)
|
||||
let baseURL = sourceURL.deletingLastPathComponent()
|
||||
try archive.addEntry(with: sourceURL.lastPathComponent, relativeTo: baseURL,
|
||||
compressionMethod: compressionMethod, progress: progress)
|
||||
}
|
||||
}
|
||||
|
||||
/// Unzips the contents at the specified source URL to the destination URL.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - 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.
|
||||
/// - progress: A progress object that can be used to track or cancel the unzip operation.
|
||||
/// - preferredEncoding: 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,
|
||||
progress: Progress? = nil, preferredEncoding: String.Encoding? = nil) throws {
|
||||
let fileManager = FileManager()
|
||||
guard fileManager.itemExists(at: sourceURL) else {
|
||||
throw CocoaError(.fileReadNoSuchFile, userInfo: [NSFilePathErrorKey: sourceURL.path])
|
||||
}
|
||||
guard let archive = Archive(url: sourceURL, accessMode: .read, preferredEncoding: preferredEncoding) else {
|
||||
throw Archive.ArchiveError.unreadableArchive
|
||||
}
|
||||
// Defer extraction of symlinks until all files & directories have been created.
|
||||
// This is necessary because we can't create links to files that haven't been created yet.
|
||||
let sortedEntries = archive.sorted { (left, right) -> Bool in
|
||||
switch (left.type, right.type) {
|
||||
case (.directory, .file): return true
|
||||
case (.directory, .symlink): return true
|
||||
case (.file, .symlink): return true
|
||||
default: return false
|
||||
}
|
||||
}
|
||||
var totalUnitCount = Int64(0)
|
||||
if let progress = progress {
|
||||
totalUnitCount = sortedEntries.reduce(0, { $0 + archive.totalUnitCountForReading($1) })
|
||||
progress.totalUnitCount = totalUnitCount
|
||||
}
|
||||
|
||||
for entry in sortedEntries {
|
||||
let path = preferredEncoding == nil ? entry.path : entry.path(using: preferredEncoding!)
|
||||
let destinationEntryURL = destinationURL.appendingPathComponent(path)
|
||||
guard destinationEntryURL.isContained(in: destinationURL) else {
|
||||
throw CocoaError(.fileReadInvalidFileName,
|
||||
userInfo: [NSFilePathErrorKey: destinationEntryURL.path])
|
||||
}
|
||||
if let progress = progress {
|
||||
let entryProgress = archive.makeProgressForReading(entry)
|
||||
progress.addChild(entryProgress, withPendingUnitCount: entryProgress.totalUnitCount)
|
||||
_ = try archive.extract(entry, to: destinationEntryURL, skipCRC32: skipCRC32, progress: entryProgress)
|
||||
} else {
|
||||
_ = try archive.extract(entry, to: destinationEntryURL, skipCRC32: skipCRC32)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
func itemExists(at url: URL) -> Bool {
|
||||
// Use `URL.checkResourceIsReachable()` instead of `FileManager.fileExists()` here
|
||||
// because we don't want implicit symlink resolution.
|
||||
// As per documentation, `FileManager.fileExists()` traverses symlinks and therefore a broken symlink
|
||||
// would throw a `.fileReadNoSuchFile` false positive error.
|
||||
// For ZIP files it may be intended to archive "broken" symlinks because they might be
|
||||
// resolvable again when extracting the archive to a different destination.
|
||||
return (try? url.checkResourceIsReachable()) == true
|
||||
}
|
||||
|
||||
func createParentDirectoryStructure(for url: URL) throws {
|
||||
let parentDirectoryURL = url.deletingLastPathComponent()
|
||||
try self.createDirectory(at: parentDirectoryURL, withIntermediateDirectories: true, attributes: nil)
|
||||
}
|
||||
|
||||
class func attributes(from entry: Entry) -> [FileAttributeKey: Any] {
|
||||
let centralDirectoryStructure = entry.centralDirectoryStructure
|
||||
let entryType = entry.type
|
||||
let fileTime = centralDirectoryStructure.lastModFileTime
|
||||
let fileDate = centralDirectoryStructure.lastModFileDate
|
||||
let defaultPermissions = entryType == .directory ? defaultDirectoryPermissions : defaultFilePermissions
|
||||
var attributes = [.posixPermissions: defaultPermissions] as [FileAttributeKey: Any]
|
||||
// Certain keys are not yet supported in swift-corelibs
|
||||
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
|
||||
attributes[.modificationDate] = Date(dateTime: (fileDate, fileTime))
|
||||
#endif
|
||||
let versionMadeBy = centralDirectoryStructure.versionMadeBy
|
||||
guard let osType = Entry.OSType(rawValue: UInt(versionMadeBy >> 8)) else { return attributes }
|
||||
|
||||
let externalFileAttributes = centralDirectoryStructure.externalFileAttributes
|
||||
let permissions = self.permissions(for: externalFileAttributes, osType: osType, entryType: entryType)
|
||||
attributes[.posixPermissions] = NSNumber(value: permissions)
|
||||
return attributes
|
||||
}
|
||||
|
||||
class func permissions(for externalFileAttributes: UInt32, osType: Entry.OSType,
|
||||
entryType: Entry.EntryType) -> UInt16 {
|
||||
switch osType {
|
||||
case .unix, .osx:
|
||||
let permissions = mode_t(externalFileAttributes >> 16) & (~S_IFMT)
|
||||
let defaultPermissions = entryType == .directory ? defaultDirectoryPermissions : defaultFilePermissions
|
||||
return permissions == 0 ? defaultPermissions : UInt16(permissions)
|
||||
default:
|
||||
return entryType == .directory ? defaultDirectoryPermissions : defaultFilePermissions
|
||||
}
|
||||
}
|
||||
|
||||
class func externalFileAttributesForEntry(of type: Entry.EntryType, permissions: UInt16) -> UInt32 {
|
||||
var typeInt: UInt16
|
||||
switch type {
|
||||
case .file:
|
||||
typeInt = UInt16(S_IFREG)
|
||||
case .directory:
|
||||
typeInt = UInt16(S_IFDIR)
|
||||
case .symlink:
|
||||
typeInt = UInt16(S_IFLNK)
|
||||
}
|
||||
var externalFileAttributes = UInt32(typeInt|UInt16(permissions))
|
||||
externalFileAttributes = (externalFileAttributes << 16)
|
||||
return externalFileAttributes
|
||||
}
|
||||
|
||||
class func permissionsForItem(at URL: URL) throws -> UInt16 {
|
||||
let fileManager = FileManager()
|
||||
let entryFileSystemRepresentation = fileManager.fileSystemRepresentation(withPath: URL.path)
|
||||
var fileStat = stat()
|
||||
lstat(entryFileSystemRepresentation, &fileStat)
|
||||
let permissions = fileStat.st_mode
|
||||
return UInt16(permissions)
|
||||
}
|
||||
|
||||
class func fileModificationDateTimeForItem(at url: URL) throws -> Date {
|
||||
let fileManager = FileManager()
|
||||
guard fileManager.itemExists(at: url) else {
|
||||
throw CocoaError(.fileReadNoSuchFile, userInfo: [NSFilePathErrorKey: url.path])
|
||||
}
|
||||
let entryFileSystemRepresentation = fileManager.fileSystemRepresentation(withPath: url.path)
|
||||
var fileStat = stat()
|
||||
lstat(entryFileSystemRepresentation, &fileStat)
|
||||
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
|
||||
let modTimeSpec = fileStat.st_mtimespec
|
||||
#else
|
||||
let modTimeSpec = fileStat.st_mtim
|
||||
#endif
|
||||
|
||||
let timeStamp = TimeInterval(modTimeSpec.tv_sec) + TimeInterval(modTimeSpec.tv_nsec)/1000000000.0
|
||||
let modDate = Date(timeIntervalSince1970: timeStamp)
|
||||
return modDate
|
||||
}
|
||||
|
||||
class func fileSizeForItem(at url: URL) throws -> UInt32 {
|
||||
let fileManager = FileManager()
|
||||
guard fileManager.itemExists(at: url) else {
|
||||
throw CocoaError(.fileReadNoSuchFile, userInfo: [NSFilePathErrorKey: url.path])
|
||||
}
|
||||
let entryFileSystemRepresentation = fileManager.fileSystemRepresentation(withPath: url.path)
|
||||
var fileStat = stat()
|
||||
lstat(entryFileSystemRepresentation, &fileStat)
|
||||
return UInt32(fileStat.st_size)
|
||||
}
|
||||
|
||||
class func typeForItem(at url: URL) throws -> Entry.EntryType {
|
||||
let fileManager = FileManager()
|
||||
guard url.isFileURL, fileManager.itemExists(at: url) else {
|
||||
throw CocoaError(.fileReadNoSuchFile, userInfo: [NSFilePathErrorKey: url.path])
|
||||
}
|
||||
let entryFileSystemRepresentation = fileManager.fileSystemRepresentation(withPath: url.path)
|
||||
var fileStat = stat()
|
||||
lstat(entryFileSystemRepresentation, &fileStat)
|
||||
return Entry.EntryType(mode: fileStat.st_mode)
|
||||
}
|
||||
}
|
||||
|
||||
extension Date {
|
||||
init(dateTime: (UInt16, UInt16)) {
|
||||
var msdosDateTime = Int(dateTime.0)
|
||||
msdosDateTime <<= 16
|
||||
msdosDateTime |= Int(dateTime.1)
|
||||
var unixTime = tm()
|
||||
unixTime.tm_sec = Int32((msdosDateTime&31)*2)
|
||||
unixTime.tm_min = Int32((msdosDateTime>>5)&63)
|
||||
unixTime.tm_hour = Int32((Int(dateTime.1)>>11)&31)
|
||||
unixTime.tm_mday = Int32((msdosDateTime>>16)&31)
|
||||
unixTime.tm_mon = Int32((msdosDateTime>>21)&15)
|
||||
unixTime.tm_mon -= 1 // UNIX time struct month entries are zero based.
|
||||
unixTime.tm_year = Int32(1980+(msdosDateTime>>25))
|
||||
unixTime.tm_year -= 1900 // UNIX time structs count in "years since 1900".
|
||||
let time = timegm(&unixTime)
|
||||
self = Date(timeIntervalSince1970: TimeInterval(time))
|
||||
}
|
||||
|
||||
var fileModificationDateTime: (UInt16, UInt16) {
|
||||
return (self.fileModificationDate, self.fileModificationTime)
|
||||
}
|
||||
|
||||
var fileModificationDate: UInt16 {
|
||||
var time = time_t(self.timeIntervalSince1970)
|
||||
guard let unixTime = gmtime(&time) else {
|
||||
return 0
|
||||
}
|
||||
var year = unixTime.pointee.tm_year + 1900 // UNIX time structs count in "years since 1900".
|
||||
// ZIP uses the MSDOS date format which has a valid range of 1980 - 2099.
|
||||
year = year >= 1980 ? year : 1980
|
||||
year = year <= 2099 ? year : 2099
|
||||
let month = unixTime.pointee.tm_mon + 1 // UNIX time struct month entries are zero based.
|
||||
let day = unixTime.pointee.tm_mday
|
||||
return (UInt16)(day + ((month) * 32) + ((year - 1980) * 512))
|
||||
}
|
||||
|
||||
var fileModificationTime: UInt16 {
|
||||
var time = time_t(self.timeIntervalSince1970)
|
||||
guard let unixTime = gmtime(&time) else {
|
||||
return 0
|
||||
}
|
||||
let hour = unixTime.pointee.tm_hour
|
||||
let minute = unixTime.pointee.tm_min
|
||||
let second = unixTime.pointee.tm_sec
|
||||
return (UInt16)((second/2) + (minute * 32) + (hour * 2048))
|
||||
}
|
||||
}
|
||||
|
||||
#if swift(>=4.2)
|
||||
#else
|
||||
|
||||
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
|
||||
#else
|
||||
|
||||
// The swift-corelibs-foundation version of NSError.swift was missing a convenience method to create
|
||||
// error objects from error codes. (https://github.com/apple/swift-corelibs-foundation/pull/1420)
|
||||
// We have to provide an implementation for non-Darwin platforms using Swift versions < 4.2.
|
||||
|
||||
public extension CocoaError {
|
||||
public static func error(_ code: CocoaError.Code, userInfo: [AnyHashable: Any]? = nil, url: URL? = nil) -> Error {
|
||||
var info: [String: Any] = userInfo as? [String: Any] ?? [:]
|
||||
if let url = url {
|
||||
info[NSURLErrorKey] = url
|
||||
}
|
||||
return NSError(domain: NSCocoaErrorDomain, code: code.rawValue, userInfo: info)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
public extension URL {
|
||||
func isContained(in parentDirectoryURL: URL) -> Bool {
|
||||
// Ensure this URL is contained in the passed in URL
|
||||
let parentDirectoryURL = URL(fileURLWithPath: parentDirectoryURL.path, isDirectory: true).standardized
|
||||
return self.standardized.absoluteString.hasPrefix(parentDirectoryURL.absoluteString)
|
||||
}
|
||||
}
|
30
third-party/ZipArchive/BUILD
vendored
Normal file
30
third-party/ZipArchive/BUILD
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
|
||||
objc_library(
|
||||
name = "ZipArchive",
|
||||
enable_modules = True,
|
||||
module_name = "ZipArchive",
|
||||
srcs = glob([
|
||||
"Sources/*.m",
|
||||
"Sources/minizip/*.h",
|
||||
"Sources/minizip/*.c",
|
||||
]),
|
||||
hdrs = glob([
|
||||
"PublicHeaders/**/*.h",
|
||||
]),
|
||||
includes = [
|
||||
"PublicHeaders",
|
||||
],
|
||||
copts = [
|
||||
"-DHAVE_ZLIB",
|
||||
"-DHAVE_INTTYPES_H",
|
||||
"-DHAVE_PKCRYPT",
|
||||
"-DHAVE_STDINT_H",
|
||||
"-DHAVE_WZAES",
|
||||
],
|
||||
sdk_frameworks = [
|
||||
"Foundation",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
],
|
||||
)
|
70
third-party/ZipArchive/PublicHeaders/ZipArchive/SSZipCommon.h
vendored
Normal file
70
third-party/ZipArchive/PublicHeaders/ZipArchive/SSZipCommon.h
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
#ifndef SSZipCommon
|
||||
#define SSZipCommon
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// typedefs moved from mz_compat.h to here for public access
|
||||
|
||||
/* unz_global_info structure contain global data about the ZIPfile
|
||||
These data comes from the end of central dir */
|
||||
typedef struct unz_global_info64_s
|
||||
{
|
||||
uint64_t number_entry; /* total number of entries in the central dir on this disk */
|
||||
uint32_t number_disk_with_CD; /* number the the disk with central dir, used for spanning ZIP */
|
||||
uint16_t size_comment; /* size of the global comment of the zipfile */
|
||||
} unz_global_info64;
|
||||
|
||||
typedef struct unz_global_info_s
|
||||
{
|
||||
uint32_t number_entry; /* total number of entries in the central dir on this disk */
|
||||
uint32_t number_disk_with_CD; /* number the the disk with central dir, used for spanning ZIP */
|
||||
uint16_t size_comment; /* size of the global comment of the zipfile */
|
||||
} unz_global_info;
|
||||
|
||||
/* unz_file_info contain information about a file in the zipfile */
|
||||
/* https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT */
|
||||
typedef struct unz_file_info64_s
|
||||
{
|
||||
uint16_t version; /* version made by 2 bytes */
|
||||
uint16_t version_needed; /* version needed to extract 2 bytes */
|
||||
uint16_t flag; /* general purpose bit flag 2 bytes */
|
||||
uint16_t compression_method; /* compression method 2 bytes */
|
||||
uint32_t dos_date; /* last mod file date in Dos fmt 4 bytes */
|
||||
uint32_t crc; /* crc-32 4 bytes */
|
||||
uint64_t compressed_size; /* compressed size 8 bytes */
|
||||
uint64_t uncompressed_size; /* uncompressed size 8 bytes */
|
||||
uint16_t size_filename; /* filename length 2 bytes */
|
||||
uint16_t size_file_extra; /* extra field length 2 bytes */
|
||||
uint16_t size_file_comment; /* file comment length 2 bytes */
|
||||
|
||||
uint32_t disk_num_start; /* disk number start 4 bytes */
|
||||
uint16_t internal_fa; /* internal file attributes 2 bytes */
|
||||
uint32_t external_fa; /* external file attributes 4 bytes */
|
||||
|
||||
uint64_t disk_offset;
|
||||
|
||||
uint16_t size_file_extra_internal;
|
||||
} unz_file_info64;
|
||||
|
||||
typedef struct unz_file_info_s
|
||||
{
|
||||
uint16_t version; /* version made by 2 bytes */
|
||||
uint16_t version_needed; /* version needed to extract 2 bytes */
|
||||
uint16_t flag; /* general purpose bit flag 2 bytes */
|
||||
uint16_t compression_method; /* compression method 2 bytes */
|
||||
uint32_t dos_date; /* last mod file date in Dos fmt 4 bytes */
|
||||
uint32_t crc; /* crc-32 4 bytes */
|
||||
uint32_t compressed_size; /* compressed size 4 bytes */
|
||||
uint32_t uncompressed_size; /* uncompressed size 4 bytes */
|
||||
uint16_t size_filename; /* filename length 2 bytes */
|
||||
uint16_t size_file_extra; /* extra field length 2 bytes */
|
||||
uint16_t size_file_comment; /* file comment length 2 bytes */
|
||||
|
||||
uint16_t disk_num_start; /* disk number start 2 bytes */
|
||||
uint16_t internal_fa; /* internal file attributes 2 bytes */
|
||||
uint32_t external_fa; /* external file attributes 4 bytes */
|
||||
|
||||
uint64_t disk_offset;
|
||||
} unz_file_info;
|
||||
|
||||
#endif
|
167
third-party/ZipArchive/PublicHeaders/ZipArchive/ZipArchive.h
vendored
Normal file
167
third-party/ZipArchive/PublicHeaders/ZipArchive/ZipArchive.h
vendored
Normal file
@ -0,0 +1,167 @@
|
||||
//
|
||||
// SSZipArchive.h
|
||||
// SSZipArchive
|
||||
//
|
||||
// Created by Sam Soffes on 7/21/10.
|
||||
// Copyright (c) Sam Soffes 2010-2015. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef _SSZIPARCHIVE_H
|
||||
#define _SSZIPARCHIVE_H
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#if COCOAPODS
|
||||
#import <SSZipArchive/SSZipCommon.h>
|
||||
#else
|
||||
#import <ZipArchive/SSZipCommon.h>
|
||||
#endif
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
extern NSString *const SSZipArchiveErrorDomain;
|
||||
typedef NS_ENUM(NSInteger, SSZipArchiveErrorCode) {
|
||||
SSZipArchiveErrorCodeFailedOpenZipFile = -1,
|
||||
SSZipArchiveErrorCodeFailedOpenFileInZip = -2,
|
||||
SSZipArchiveErrorCodeFileInfoNotLoadable = -3,
|
||||
SSZipArchiveErrorCodeFileContentNotReadable = -4,
|
||||
SSZipArchiveErrorCodeFailedToWriteFile = -5,
|
||||
SSZipArchiveErrorCodeInvalidArguments = -6,
|
||||
};
|
||||
|
||||
@protocol SSZipArchiveDelegate;
|
||||
|
||||
@interface SSZipEntry : NSObject
|
||||
|
||||
@property (nonatomic, strong, readonly) NSString *path;
|
||||
@property (nonatomic, readonly) NSUInteger uncompressedSize;
|
||||
|
||||
- (instancetype)initWithPath:(NSString *)path uncompressedSize:(NSUInteger)uncompressedSize;
|
||||
|
||||
@end
|
||||
|
||||
@interface SSZipArchive : NSObject
|
||||
|
||||
+ (NSArray<SSZipEntry *> * _Nullable)getEntriesForFileAtPath:(NSString *)path;
|
||||
+ (BOOL)extractFileFromArchiveAtPath:(NSString *)path filePath:(NSString *)filePath toPath:(NSString *)toPath;
|
||||
|
||||
// Password check
|
||||
+ (BOOL)isFilePasswordProtectedAtPath:(NSString *)path;
|
||||
+ (BOOL)isPasswordValidForArchiveAtPath:(NSString *)path password:(NSString *)pw error:(NSError * _Nullable * _Nullable)error NS_SWIFT_NOTHROW;
|
||||
|
||||
// Total payload size
|
||||
+ (NSNumber *)payloadSizeForArchiveAtPath:(NSString *)path error:(NSError **)error;
|
||||
|
||||
// Unzip
|
||||
+ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination;
|
||||
+ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination delegate:(nullable id<SSZipArchiveDelegate>)delegate;
|
||||
|
||||
+ (BOOL)unzipFileAtPath:(NSString *)path
|
||||
toDestination:(NSString *)destination
|
||||
overwrite:(BOOL)overwrite
|
||||
password:(nullable NSString *)password
|
||||
error:(NSError * *)error;
|
||||
|
||||
+ (BOOL)unzipFileAtPath:(NSString *)path
|
||||
toDestination:(NSString *)destination
|
||||
overwrite:(BOOL)overwrite
|
||||
password:(nullable NSString *)password
|
||||
error:(NSError * *)error
|
||||
delegate:(nullable id<SSZipArchiveDelegate>)delegate NS_REFINED_FOR_SWIFT;
|
||||
|
||||
+ (BOOL)unzipFileAtPath:(NSString *)path
|
||||
toDestination:(NSString *)destination
|
||||
preserveAttributes:(BOOL)preserveAttributes
|
||||
overwrite:(BOOL)overwrite
|
||||
password:(nullable NSString *)password
|
||||
error:(NSError * *)error
|
||||
delegate:(nullable id<SSZipArchiveDelegate>)delegate;
|
||||
|
||||
+ (BOOL)unzipFileAtPath:(NSString *)path
|
||||
toDestination:(NSString *)destination
|
||||
progressHandler:(void (^_Nullable)(NSString *entry, unz_file_info zipInfo, long entryNumber, long total))progressHandler
|
||||
completionHandler:(void (^_Nullable)(NSString *path, BOOL succeeded, NSError * _Nullable error))completionHandler;
|
||||
|
||||
+ (BOOL)unzipFileAtPath:(NSString *)path
|
||||
toDestination:(NSString *)destination
|
||||
overwrite:(BOOL)overwrite
|
||||
password:(nullable NSString *)password
|
||||
progressHandler:(void (^_Nullable)(NSString *entry, unz_file_info zipInfo, long entryNumber, long total))progressHandler
|
||||
completionHandler:(void (^_Nullable)(NSString *path, BOOL succeeded, NSError * _Nullable error))completionHandler;
|
||||
|
||||
+ (BOOL)unzipFileAtPath:(NSString *)path
|
||||
toDestination:(NSString *)destination
|
||||
preserveAttributes:(BOOL)preserveAttributes
|
||||
overwrite:(BOOL)overwrite
|
||||
nestedZipLevel:(NSInteger)nestedZipLevel
|
||||
password:(nullable NSString *)password
|
||||
error:(NSError **)error
|
||||
delegate:(nullable id<SSZipArchiveDelegate>)delegate
|
||||
progressHandler:(void (^_Nullable)(NSString *entry, unz_file_info zipInfo, long entryNumber, long total))progressHandler
|
||||
completionHandler:(void (^_Nullable)(NSString *path, BOOL succeeded, NSError * _Nullable error))completionHandler;
|
||||
|
||||
// Zip
|
||||
// default compression level is Z_DEFAULT_COMPRESSION (from "zlib.h")
|
||||
// keepParentDirectory: if YES, then unzipping will give `directoryName/fileName`. If NO, then unzipping will just give `fileName`. Default is NO.
|
||||
|
||||
// without password
|
||||
+ (BOOL)createZipFileAtPath:(NSString *)path withFilesAtPaths:(NSArray<NSString *> *)paths;
|
||||
+ (BOOL)createZipFileAtPath:(NSString *)path withContentsOfDirectory:(NSString *)directoryPath;
|
||||
|
||||
+ (BOOL)createZipFileAtPath:(NSString *)path withContentsOfDirectory:(NSString *)directoryPath keepParentDirectory:(BOOL)keepParentDirectory;
|
||||
|
||||
// with optional password, default encryption is AES
|
||||
// don't use AES if you need compatibility with native macOS unzip and Archive Utility
|
||||
+ (BOOL)createZipFileAtPath:(NSString *)path withFilesAtPaths:(NSArray<NSString *> *)paths withPassword:(nullable NSString *)password;
|
||||
+ (BOOL)createZipFileAtPath:(NSString *)path withContentsOfDirectory:(NSString *)directoryPath withPassword:(nullable NSString *)password;
|
||||
+ (BOOL)createZipFileAtPath:(NSString *)path withContentsOfDirectory:(NSString *)directoryPath keepParentDirectory:(BOOL)keepParentDirectory withPassword:(nullable NSString *)password;
|
||||
+ (BOOL)createZipFileAtPath:(NSString *)path
|
||||
withContentsOfDirectory:(NSString *)directoryPath
|
||||
keepParentDirectory:(BOOL)keepParentDirectory
|
||||
withPassword:(nullable NSString *)password
|
||||
andProgressHandler:(void(^ _Nullable)(NSUInteger entryNumber, NSUInteger total))progressHandler;
|
||||
+ (BOOL)createZipFileAtPath:(NSString *)path
|
||||
withContentsOfDirectory:(NSString *)directoryPath
|
||||
keepParentDirectory:(BOOL)keepParentDirectory
|
||||
compressionLevel:(int)compressionLevel
|
||||
password:(nullable NSString *)password
|
||||
AES:(BOOL)aes
|
||||
progressHandler:(void(^ _Nullable)(NSUInteger entryNumber, NSUInteger total))progressHandler;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
- (instancetype)initWithPath:(NSString *)path NS_DESIGNATED_INITIALIZER;
|
||||
- (BOOL)open;
|
||||
|
||||
/// write empty folder
|
||||
- (BOOL)writeFolderAtPath:(NSString *)path withFolderName:(NSString *)folderName withPassword:(nullable NSString *)password;
|
||||
/// write file
|
||||
- (BOOL)writeFile:(NSString *)path withPassword:(nullable NSString *)password;
|
||||
- (BOOL)writeFileAtPath:(NSString *)path withFileName:(nullable NSString *)fileName withPassword:(nullable NSString *)password;
|
||||
- (BOOL)writeFileAtPath:(NSString *)path withFileName:(nullable NSString *)fileName compressionLevel:(int)compressionLevel password:(nullable NSString *)password AES:(BOOL)aes;
|
||||
/// write data
|
||||
- (BOOL)writeData:(NSData *)data filename:(nullable NSString *)filename withPassword:(nullable NSString *)password;
|
||||
- (BOOL)writeData:(NSData *)data filename:(nullable NSString *)filename compressionLevel:(int)compressionLevel password:(nullable NSString *)password AES:(BOOL)aes;
|
||||
|
||||
- (BOOL)close;
|
||||
|
||||
@end
|
||||
|
||||
@protocol SSZipArchiveDelegate <NSObject>
|
||||
|
||||
@optional
|
||||
|
||||
- (void)zipArchiveWillUnzipArchiveAtPath:(NSString *)path zipInfo:(unz_global_info)zipInfo;
|
||||
- (void)zipArchiveDidUnzipArchiveAtPath:(NSString *)path zipInfo:(unz_global_info)zipInfo unzippedPath:(NSString *)unzippedPath;
|
||||
|
||||
- (BOOL)zipArchiveShouldUnzipFileAtIndex:(NSInteger)fileIndex totalFiles:(NSInteger)totalFiles archivePath:(NSString *)archivePath fileInfo:(unz_file_info)fileInfo;
|
||||
- (void)zipArchiveWillUnzipFileAtIndex:(NSInteger)fileIndex totalFiles:(NSInteger)totalFiles archivePath:(NSString *)archivePath fileInfo:(unz_file_info)fileInfo;
|
||||
- (void)zipArchiveDidUnzipFileAtIndex:(NSInteger)fileIndex totalFiles:(NSInteger)totalFiles archivePath:(NSString *)archivePath fileInfo:(unz_file_info)fileInfo;
|
||||
- (void)zipArchiveDidUnzipFileAtIndex:(NSInteger)fileIndex totalFiles:(NSInteger)totalFiles archivePath:(NSString *)archivePath unzippedFilePath:(NSString *)unzippedFilePath;
|
||||
|
||||
- (void)zipArchiveProgressEvent:(unsigned long long)loaded total:(unsigned long long)total;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif /* _SSZIPARCHIVE_H */
|
1625
third-party/ZipArchive/Sources/SSZipArchive.m
vendored
Normal file
1625
third-party/ZipArchive/Sources/SSZipArchive.m
vendored
Normal file
File diff suppressed because it is too large
Load Diff
17
third-party/ZipArchive/Sources/minizip/LICENSE
vendored
Normal file
17
third-party/ZipArchive/Sources/minizip/LICENSE
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
Condition of use and distribution are the same as zlib:
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgement in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
252
third-party/ZipArchive/Sources/minizip/mz.h
vendored
Normal file
252
third-party/ZipArchive/Sources/minizip/mz.h
vendored
Normal file
@ -0,0 +1,252 @@
|
||||
/* mz.h -- Errors codes, zip flags and magic
|
||||
Version 2.9.2, February 12, 2020
|
||||
part of the MiniZip project
|
||||
|
||||
Copyright (C) 2010-2020 Nathan Moinvaziri
|
||||
https://github.com/nmoinvaz/minizip
|
||||
|
||||
This program is distributed under the terms of the same license as zlib.
|
||||
See the accompanying LICENSE file for the full text of the license.
|
||||
*/
|
||||
|
||||
#ifndef MZ_H
|
||||
#define MZ_H
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/* MZ_VERSION */
|
||||
#define MZ_VERSION ("2.9.2")
|
||||
|
||||
/* MZ_ERROR */
|
||||
#define MZ_OK (0) /* zlib */
|
||||
#define MZ_STREAM_ERROR (-1) /* zlib */
|
||||
#define MZ_DATA_ERROR (-3) /* zlib */
|
||||
#define MZ_MEM_ERROR (-4) /* zlib */
|
||||
#define MZ_BUF_ERROR (-5) /* zlib */
|
||||
#define MZ_VERSION_ERROR (-6) /* zlib */
|
||||
|
||||
#define MZ_END_OF_LIST (-100)
|
||||
#define MZ_END_OF_STREAM (-101)
|
||||
|
||||
#define MZ_PARAM_ERROR (-102)
|
||||
#define MZ_FORMAT_ERROR (-103)
|
||||
#define MZ_INTERNAL_ERROR (-104)
|
||||
#define MZ_CRC_ERROR (-105)
|
||||
#define MZ_CRYPT_ERROR (-106)
|
||||
#define MZ_EXIST_ERROR (-107)
|
||||
#define MZ_PASSWORD_ERROR (-108)
|
||||
#define MZ_SUPPORT_ERROR (-109)
|
||||
#define MZ_HASH_ERROR (-110)
|
||||
#define MZ_OPEN_ERROR (-111)
|
||||
#define MZ_CLOSE_ERROR (-112)
|
||||
#define MZ_SEEK_ERROR (-113)
|
||||
#define MZ_TELL_ERROR (-114)
|
||||
#define MZ_READ_ERROR (-115)
|
||||
#define MZ_WRITE_ERROR (-116)
|
||||
#define MZ_SIGN_ERROR (-117)
|
||||
#define MZ_SYMLINK_ERROR (-118)
|
||||
|
||||
/* MZ_OPEN */
|
||||
#define MZ_OPEN_MODE_READ (0x01)
|
||||
#define MZ_OPEN_MODE_WRITE (0x02)
|
||||
#define MZ_OPEN_MODE_READWRITE (MZ_OPEN_MODE_READ | MZ_OPEN_MODE_WRITE)
|
||||
#define MZ_OPEN_MODE_APPEND (0x04)
|
||||
#define MZ_OPEN_MODE_CREATE (0x08)
|
||||
#define MZ_OPEN_MODE_EXISTING (0x10)
|
||||
|
||||
/* MZ_SEEK */
|
||||
#define MZ_SEEK_SET (0)
|
||||
#define MZ_SEEK_CUR (1)
|
||||
#define MZ_SEEK_END (2)
|
||||
|
||||
/* MZ_COMPRESS */
|
||||
#define MZ_COMPRESS_METHOD_STORE (0)
|
||||
#define MZ_COMPRESS_METHOD_DEFLATE (8)
|
||||
#define MZ_COMPRESS_METHOD_BZIP2 (12)
|
||||
#define MZ_COMPRESS_METHOD_LZMA (14)
|
||||
#define MZ_COMPRESS_METHOD_AES (99)
|
||||
|
||||
#define MZ_COMPRESS_LEVEL_DEFAULT (-1)
|
||||
#define MZ_COMPRESS_LEVEL_FAST (2)
|
||||
#define MZ_COMPRESS_LEVEL_NORMAL (6)
|
||||
#define MZ_COMPRESS_LEVEL_BEST (9)
|
||||
|
||||
/* MZ_ZIP_FLAG */
|
||||
#define MZ_ZIP_FLAG_ENCRYPTED (1 << 0)
|
||||
#define MZ_ZIP_FLAG_LZMA_EOS_MARKER (1 << 1)
|
||||
#define MZ_ZIP_FLAG_DEFLATE_MAX (1 << 1)
|
||||
#define MZ_ZIP_FLAG_DEFLATE_NORMAL (0)
|
||||
#define MZ_ZIP_FLAG_DEFLATE_FAST (1 << 2)
|
||||
#define MZ_ZIP_FLAG_DEFLATE_SUPER_FAST (MZ_ZIP_FLAG_DEFLATE_FAST | \
|
||||
MZ_ZIP_FLAG_DEFLATE_MAX)
|
||||
#define MZ_ZIP_FLAG_DATA_DESCRIPTOR (1 << 3)
|
||||
#define MZ_ZIP_FLAG_UTF8 (1 << 11)
|
||||
#define MZ_ZIP_FLAG_MASK_LOCAL_INFO (1 << 13)
|
||||
|
||||
/* MZ_ZIP_EXTENSION */
|
||||
#define MZ_ZIP_EXTENSION_ZIP64 (0x0001)
|
||||
#define MZ_ZIP_EXTENSION_NTFS (0x000a)
|
||||
#define MZ_ZIP_EXTENSION_AES (0x9901)
|
||||
#define MZ_ZIP_EXTENSION_UNIX1 (0x000d)
|
||||
#define MZ_ZIP_EXTENSION_SIGN (0x10c5)
|
||||
#define MZ_ZIP_EXTENSION_HASH (0x1a51)
|
||||
#define MZ_ZIP_EXTENSION_CDCD (0xcdcd)
|
||||
|
||||
/* MZ_ZIP64 */
|
||||
#define MZ_ZIP64_AUTO (0)
|
||||
#define MZ_ZIP64_FORCE (1)
|
||||
#define MZ_ZIP64_DISABLE (2)
|
||||
|
||||
/* MZ_HOST_SYSTEM */
|
||||
#define MZ_HOST_SYSTEM(VERSION_MADEBY) ((uint8_t)(VERSION_MADEBY >> 8))
|
||||
#define MZ_HOST_SYSTEM_MSDOS (0)
|
||||
#define MZ_HOST_SYSTEM_UNIX (3)
|
||||
#define MZ_HOST_SYSTEM_WINDOWS_NTFS (10)
|
||||
#define MZ_HOST_SYSTEM_RISCOS (13)
|
||||
#define MZ_HOST_SYSTEM_OSX_DARWIN (19)
|
||||
|
||||
/* MZ_PKCRYPT */
|
||||
#define MZ_PKCRYPT_HEADER_SIZE (12)
|
||||
|
||||
/* MZ_AES */
|
||||
#define MZ_AES_VERSION (1)
|
||||
#define MZ_AES_ENCRYPTION_MODE_128 (0x01)
|
||||
#define MZ_AES_ENCRYPTION_MODE_192 (0x02)
|
||||
#define MZ_AES_ENCRYPTION_MODE_256 (0x03)
|
||||
#define MZ_AES_KEY_LENGTH(MODE) (8 * (MODE & 3) + 8)
|
||||
#define MZ_AES_KEY_LENGTH_MAX (32)
|
||||
#define MZ_AES_BLOCK_SIZE (16)
|
||||
#define MZ_AES_HEADER_SIZE(MODE) ((4 * (MODE & 3) + 4) + 2)
|
||||
#define MZ_AES_FOOTER_SIZE (10)
|
||||
|
||||
/* MZ_HASH */
|
||||
#define MZ_HASH_MD5 (10)
|
||||
#define MZ_HASH_MD5_SIZE (16)
|
||||
#define MZ_HASH_SHA1 (20)
|
||||
#define MZ_HASH_SHA1_SIZE (20)
|
||||
#define MZ_HASH_SHA256 (23)
|
||||
#define MZ_HASH_SHA256_SIZE (32)
|
||||
#define MZ_HASH_MAX_SIZE (256)
|
||||
|
||||
/* MZ_ENCODING */
|
||||
#define MZ_ENCODING_CODEPAGE_437 (437)
|
||||
#define MZ_ENCODING_CODEPAGE_932 (932)
|
||||
#define MZ_ENCODING_CODEPAGE_936 (936)
|
||||
#define MZ_ENCODING_CODEPAGE_950 (950)
|
||||
#define MZ_ENCODING_UTF8 (65001)
|
||||
|
||||
/* MZ_UTILITY */
|
||||
#define MZ_UNUSED(SYMBOL) ((void)SYMBOL)
|
||||
|
||||
#ifndef MZ_CUSTOM_ALLOC
|
||||
#define MZ_ALLOC(SIZE) (malloc(SIZE))
|
||||
#endif
|
||||
#ifndef MZ_CUSTOM_FREE
|
||||
#define MZ_FREE(PTR) (free(PTR))
|
||||
#endif
|
||||
|
||||
#if defined(_WINDOWS) && defined(MZ_EXPORTS)
|
||||
#define MZ_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define MZ_EXPORT
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#include <stdlib.h> /* size_t, NULL, malloc */
|
||||
#include <time.h> /* time_t, time() */
|
||||
#include <string.h> /* memset, strncpy, strlen */
|
||||
#include <limits.h>
|
||||
|
||||
#ifdef HAVE_STDINT_H
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
|
||||
#ifndef __INT8_TYPE__
|
||||
typedef signed char int8_t;
|
||||
#endif
|
||||
#ifndef __INT16_TYPE__
|
||||
typedef short int16_t;
|
||||
#endif
|
||||
#ifndef __INT32_TYPE__
|
||||
typedef int int32_t;
|
||||
#endif
|
||||
#ifndef __INT64_TYPE__
|
||||
typedef long long int64_t;
|
||||
#endif
|
||||
#ifndef __UINT8_TYPE__
|
||||
typedef unsigned char uint8_t;
|
||||
#endif
|
||||
#ifndef __UINT16_TYPE__
|
||||
typedef unsigned short uint16_t;
|
||||
#endif
|
||||
#ifndef __UINT32_TYPE__
|
||||
typedef unsigned int uint32_t;
|
||||
#endif
|
||||
#ifndef __UINT64_TYPE__
|
||||
typedef unsigned long long uint64_t;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_INTTYPES_H
|
||||
# include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#ifndef PRId8
|
||||
# define PRId8 "hhd"
|
||||
#endif
|
||||
#ifndef PRId16
|
||||
# define PRId16 "hd"
|
||||
#endif
|
||||
#ifndef PRId32
|
||||
# define PRId32 "d"
|
||||
#endif
|
||||
#ifndef PRIu32
|
||||
# define PRIu32 "u"
|
||||
#endif
|
||||
#ifndef PRIx32
|
||||
# define PRIx32 "x"
|
||||
#endif
|
||||
#if ULONG_MAX == 4294967295UL
|
||||
# ifndef PRId64
|
||||
# define PRId64 "lld"
|
||||
# endif
|
||||
# ifndef PRIu64
|
||||
# define PRIu64 "llu"
|
||||
# endif
|
||||
# ifndef PRIx64
|
||||
# define PRIx64 "llx"
|
||||
# endif
|
||||
#else
|
||||
# ifndef PRId64
|
||||
# define PRId64 "ld"
|
||||
# endif
|
||||
# ifndef PRIu64
|
||||
# define PRIu64 "lu"
|
||||
# endif
|
||||
# ifndef PRIx64
|
||||
# define PRIx64 "lx"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef INT16_MAX
|
||||
# define INT16_MAX 32767
|
||||
#endif
|
||||
#ifndef INT32_MAX
|
||||
# define INT32_MAX 2147483647L
|
||||
#endif
|
||||
#ifndef INT64_MAX
|
||||
# define INT64_MAX 9223372036854775807LL
|
||||
#endif
|
||||
#ifndef UINT16_MAX
|
||||
# define UINT16_MAX 65535U
|
||||
#endif
|
||||
#ifndef UINT32_MAX
|
||||
# define UINT32_MAX 4294967295UL
|
||||
#endif
|
||||
#ifndef UINT64_MAX
|
||||
# define UINT64_MAX 18446744073709551615ULL
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#endif
|
991
third-party/ZipArchive/Sources/minizip/mz_compat.c
vendored
Normal file
991
third-party/ZipArchive/Sources/minizip/mz_compat.c
vendored
Normal file
@ -0,0 +1,991 @@
|
||||
/* mz_compat.c -- Backwards compatible interface for older versions
|
||||
Version 2.8.9, July 4, 2019
|
||||
part of the MiniZip project
|
||||
|
||||
Copyright (C) 2010-2019 Nathan Moinvaziri
|
||||
https://github.com/nmoinvaz/minizip
|
||||
Copyright (C) 1998-2010 Gilles Vollant
|
||||
https://www.winimage.com/zLibDll/minizip.html
|
||||
|
||||
This program is distributed under the terms of the same license as zlib.
|
||||
See the accompanying LICENSE file for the full text of the license.
|
||||
*/
|
||||
|
||||
|
||||
#include "mz.h"
|
||||
#include "mz_os.h"
|
||||
#include "mz_strm.h"
|
||||
#include "mz_strm_mem.h"
|
||||
#include "mz_strm_os.h"
|
||||
#include "mz_strm_zlib.h"
|
||||
#include "mz_zip.h"
|
||||
|
||||
#include <stdio.h> /* SEEK */
|
||||
|
||||
#include "mz_compat.h"
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
typedef struct mz_compat_s {
|
||||
void *stream;
|
||||
void *handle;
|
||||
uint64_t entry_index;
|
||||
int64_t entry_pos;
|
||||
int64_t total_out;
|
||||
} mz_compat;
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
static int32_t zipConvertAppendToStreamMode(int append)
|
||||
{
|
||||
int32_t mode = MZ_OPEN_MODE_WRITE;
|
||||
switch (append)
|
||||
{
|
||||
case APPEND_STATUS_CREATE:
|
||||
mode |= MZ_OPEN_MODE_CREATE;
|
||||
break;
|
||||
case APPEND_STATUS_CREATEAFTER:
|
||||
mode |= MZ_OPEN_MODE_CREATE | MZ_OPEN_MODE_APPEND;
|
||||
break;
|
||||
case APPEND_STATUS_ADDINZIP:
|
||||
mode |= MZ_OPEN_MODE_READ | MZ_OPEN_MODE_APPEND;
|
||||
break;
|
||||
}
|
||||
return mode;
|
||||
}
|
||||
|
||||
zipFile zipOpen(const char *path, int append)
|
||||
{
|
||||
zlib_filefunc64_def pzlib = mz_stream_os_get_interface();
|
||||
return zipOpen2(path, append, NULL, &pzlib);
|
||||
}
|
||||
|
||||
zipFile zipOpen64(const void *path, int append)
|
||||
{
|
||||
zlib_filefunc64_def pzlib = mz_stream_os_get_interface();
|
||||
return zipOpen2(path, append, NULL, &pzlib);
|
||||
}
|
||||
|
||||
zipFile zipOpen2(const char *path, int append, const char **globalcomment,
|
||||
zlib_filefunc_def *pzlib_filefunc_def)
|
||||
{
|
||||
return zipOpen2_64(path, append, globalcomment, pzlib_filefunc_def);
|
||||
}
|
||||
|
||||
zipFile zipOpen2_64(const void *path, int append, const char **globalcomment,
|
||||
zlib_filefunc64_def *pzlib_filefunc_def)
|
||||
{
|
||||
zipFile zip = NULL;
|
||||
int32_t mode = zipConvertAppendToStreamMode(append);
|
||||
void *stream = NULL;
|
||||
|
||||
if (pzlib_filefunc_def)
|
||||
{
|
||||
if (mz_stream_create(&stream, (mz_stream_vtbl *)*pzlib_filefunc_def) == NULL)
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mz_stream_os_create(&stream) == NULL)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (mz_stream_open(stream, path, mode) != MZ_OK)
|
||||
{
|
||||
mz_stream_delete(&stream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
zip = zipOpen_MZ(stream, append, globalcomment);
|
||||
|
||||
if (zip == NULL)
|
||||
{
|
||||
mz_stream_delete(&stream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return zip;
|
||||
}
|
||||
|
||||
zipFile zipOpen_MZ(void *stream, int append, const char **globalcomment)
|
||||
{
|
||||
mz_compat *compat = NULL;
|
||||
int32_t err = MZ_OK;
|
||||
int32_t mode = zipConvertAppendToStreamMode(append);
|
||||
void *handle = NULL;
|
||||
|
||||
mz_zip_create(&handle);
|
||||
err = mz_zip_open(handle, stream, mode);
|
||||
|
||||
if (err != MZ_OK)
|
||||
{
|
||||
mz_zip_delete(&handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (globalcomment != NULL)
|
||||
mz_zip_get_comment(handle, globalcomment);
|
||||
|
||||
compat = (mz_compat *)MZ_ALLOC(sizeof(mz_compat));
|
||||
if (compat != NULL)
|
||||
{
|
||||
compat->handle = handle;
|
||||
compat->stream = stream;
|
||||
}
|
||||
else
|
||||
{
|
||||
mz_zip_delete(&handle);
|
||||
}
|
||||
|
||||
return (zipFile)compat;
|
||||
}
|
||||
|
||||
int zipOpenNewFileInZip5(zipFile file, const char *filename, const zip_fileinfo *zipfi,
|
||||
const void *extrafield_local, uint16_t size_extrafield_local, const void *extrafield_global,
|
||||
uint16_t size_extrafield_global, const char *comment, uint16_t compression_method, int level,
|
||||
int raw, int windowBits, int memLevel, int strategy, const char *password,
|
||||
signed char aes, uint16_t version_madeby, uint16_t flag_base, int zip64)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
mz_zip_file file_info;
|
||||
uint64_t dos_date = 0;
|
||||
|
||||
MZ_UNUSED(strategy);
|
||||
MZ_UNUSED(memLevel);
|
||||
MZ_UNUSED(windowBits);
|
||||
MZ_UNUSED(size_extrafield_local);
|
||||
MZ_UNUSED(extrafield_local);
|
||||
|
||||
if (compat == NULL)
|
||||
return ZIP_PARAMERROR;
|
||||
|
||||
memset(&file_info, 0, sizeof(file_info));
|
||||
|
||||
if (zipfi != NULL)
|
||||
{
|
||||
if (zipfi->mz_dos_date != 0)
|
||||
dos_date = zipfi->mz_dos_date;
|
||||
else
|
||||
dos_date = mz_zip_tm_to_dosdate(&zipfi->tmz_date);
|
||||
|
||||
file_info.modified_date = mz_zip_dosdate_to_time_t(dos_date);
|
||||
file_info.external_fa = zipfi->external_fa;
|
||||
file_info.internal_fa = zipfi->internal_fa;
|
||||
}
|
||||
|
||||
if (filename == NULL)
|
||||
filename = "-";
|
||||
|
||||
file_info.compression_method = compression_method;
|
||||
file_info.filename = filename;
|
||||
/* file_info.extrafield_local = extrafield_local; */
|
||||
/* file_info.extrafield_local_size = size_extrafield_local; */
|
||||
file_info.extrafield = extrafield_global;
|
||||
file_info.extrafield_size = size_extrafield_global;
|
||||
file_info.version_madeby = version_madeby;
|
||||
file_info.comment = comment;
|
||||
file_info.flag = flag_base;
|
||||
if (zip64)
|
||||
file_info.zip64 = MZ_ZIP64_FORCE;
|
||||
else
|
||||
file_info.zip64 = MZ_ZIP64_DISABLE;
|
||||
#ifdef HAVE_WZAES
|
||||
if ((aes && password != NULL) || (raw && (file_info.flag & MZ_ZIP_FLAG_ENCRYPTED)))
|
||||
file_info.aes_version = MZ_AES_VERSION;
|
||||
#endif
|
||||
|
||||
return mz_zip_entry_write_open(compat->handle, &file_info, (int16_t)level, (uint8_t)raw, password);
|
||||
}
|
||||
|
||||
int zipWriteInFileInZip(zipFile file, const void *buf, uint32_t len)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
int32_t written = 0;
|
||||
if (compat == NULL || len >= INT32_MAX)
|
||||
return ZIP_PARAMERROR;
|
||||
written = mz_zip_entry_write(compat->handle, buf, (int32_t)len);
|
||||
if ((written < 0) || ((uint32_t)written != len))
|
||||
return ZIP_ERRNO;
|
||||
return ZIP_OK;
|
||||
}
|
||||
|
||||
int zipCloseFileInZipRaw(zipFile file, uint32_t uncompressed_size, uint32_t crc32)
|
||||
{
|
||||
return zipCloseFileInZipRaw64(file, uncompressed_size, crc32);
|
||||
}
|
||||
|
||||
int zipCloseFileInZipRaw64(zipFile file, int64_t uncompressed_size, uint32_t crc32)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
if (compat == NULL)
|
||||
return ZIP_PARAMERROR;
|
||||
return mz_zip_entry_close_raw(compat->handle, uncompressed_size, crc32);
|
||||
}
|
||||
|
||||
int zipCloseFileInZip(zipFile file)
|
||||
{
|
||||
return zipCloseFileInZip64(file);
|
||||
}
|
||||
|
||||
int zipCloseFileInZip64(zipFile file)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
if (compat == NULL)
|
||||
return ZIP_PARAMERROR;
|
||||
return mz_zip_entry_close(compat->handle);
|
||||
}
|
||||
|
||||
int zipClose(zipFile file, const char *global_comment)
|
||||
{
|
||||
return zipClose_64(file, global_comment);
|
||||
}
|
||||
|
||||
int zipClose_64(zipFile file, const char *global_comment)
|
||||
{
|
||||
return zipClose2_64(file, global_comment, MZ_VERSION_MADEBY);
|
||||
}
|
||||
|
||||
int zipClose2_64(zipFile file, const char *global_comment, uint16_t version_madeby)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
int32_t err = MZ_OK;
|
||||
|
||||
if (compat->handle != NULL)
|
||||
err = zipClose2_MZ(file, global_comment, version_madeby);
|
||||
|
||||
if (compat->stream != NULL)
|
||||
{
|
||||
mz_stream_close(compat->stream);
|
||||
mz_stream_delete(&compat->stream);
|
||||
}
|
||||
|
||||
MZ_FREE(compat);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Only closes the zip handle, does not close the stream */
|
||||
int zipClose_MZ(zipFile file, const char *global_comment)
|
||||
{
|
||||
return zipClose2_MZ(file, global_comment, MZ_VERSION_MADEBY);
|
||||
}
|
||||
|
||||
/* Only closes the zip handle, does not close the stream */
|
||||
int zipClose2_MZ(zipFile file, const char *global_comment, uint16_t version_madeby)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
int32_t err = MZ_OK;
|
||||
|
||||
if (compat == NULL)
|
||||
return ZIP_PARAMERROR;
|
||||
if (compat->handle == NULL)
|
||||
return err;
|
||||
|
||||
if (global_comment != NULL)
|
||||
mz_zip_set_comment(compat->handle, global_comment);
|
||||
|
||||
mz_zip_set_version_madeby(compat->handle, version_madeby);
|
||||
err = mz_zip_close(compat->handle);
|
||||
mz_zip_delete(&compat->handle);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void* zipGetStream(zipFile file)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
if (compat == NULL)
|
||||
return NULL;
|
||||
return (void *)compat->stream;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
unzFile unzOpen(const char *path)
|
||||
{
|
||||
return unzOpen64(path);
|
||||
}
|
||||
|
||||
unzFile unzOpen64(const void *path)
|
||||
{
|
||||
zlib_filefunc64_def pzlib = mz_stream_os_get_interface();
|
||||
return unzOpen2(path, &pzlib);
|
||||
}
|
||||
|
||||
unzFile unzOpen2(const char *path, zlib_filefunc_def *pzlib_filefunc_def)
|
||||
{
|
||||
return unzOpen2_64(path, pzlib_filefunc_def);
|
||||
}
|
||||
|
||||
unzFile unzOpen2_64(const void *path, zlib_filefunc64_def *pzlib_filefunc_def)
|
||||
{
|
||||
unzFile unz = NULL;
|
||||
void *stream = NULL;
|
||||
|
||||
if (pzlib_filefunc_def)
|
||||
{
|
||||
if (mz_stream_create(&stream, (mz_stream_vtbl *)*pzlib_filefunc_def) == NULL)
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mz_stream_os_create(&stream) == NULL)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (mz_stream_open(stream, path, MZ_OPEN_MODE_READ) != MZ_OK)
|
||||
{
|
||||
mz_stream_delete(&stream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unz = unzOpen_MZ(stream);
|
||||
if (unz == NULL)
|
||||
{
|
||||
mz_stream_delete(&stream);
|
||||
return NULL;
|
||||
}
|
||||
return unz;
|
||||
}
|
||||
|
||||
unzFile unzOpen_MZ(void *stream)
|
||||
{
|
||||
mz_compat *compat = NULL;
|
||||
int32_t err = MZ_OK;
|
||||
void *handle = NULL;
|
||||
|
||||
mz_zip_create(&handle);
|
||||
err = mz_zip_open(handle, stream, MZ_OPEN_MODE_READ);
|
||||
|
||||
if (err != MZ_OK)
|
||||
{
|
||||
mz_zip_delete(&handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
compat = (mz_compat *)MZ_ALLOC(sizeof(mz_compat));
|
||||
if (compat != NULL)
|
||||
{
|
||||
compat->handle = handle;
|
||||
compat->stream = stream;
|
||||
|
||||
mz_zip_goto_first_entry(compat->handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
mz_zip_delete(&handle);
|
||||
}
|
||||
|
||||
return (unzFile)compat;
|
||||
}
|
||||
|
||||
int unzClose(unzFile file)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
int32_t err = MZ_OK;
|
||||
|
||||
if (compat == NULL)
|
||||
return UNZ_PARAMERROR;
|
||||
|
||||
if (compat->handle != NULL)
|
||||
err = unzClose_MZ(file);
|
||||
|
||||
if (compat->stream != NULL)
|
||||
{
|
||||
mz_stream_close(compat->stream);
|
||||
mz_stream_delete(&compat->stream);
|
||||
}
|
||||
|
||||
MZ_FREE(compat);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Only closes the zip handle, does not close the stream */
|
||||
int unzClose_MZ(unzFile file)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
int32_t err = MZ_OK;
|
||||
|
||||
if (compat == NULL)
|
||||
return UNZ_PARAMERROR;
|
||||
|
||||
err = mz_zip_close(compat->handle);
|
||||
mz_zip_delete(&compat->handle);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int unzGetGlobalInfo(unzFile file, unz_global_info* pglobal_info32)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
unz_global_info64 global_info64;
|
||||
int32_t err = MZ_OK;
|
||||
|
||||
memset(pglobal_info32, 0, sizeof(unz_global_info));
|
||||
if (compat == NULL)
|
||||
return UNZ_PARAMERROR;
|
||||
|
||||
err = unzGetGlobalInfo64(file, &global_info64);
|
||||
if (err == MZ_OK)
|
||||
{
|
||||
pglobal_info32->number_entry = (uint32_t)global_info64.number_entry;
|
||||
pglobal_info32->size_comment = global_info64.size_comment;
|
||||
pglobal_info32->number_disk_with_CD = global_info64.number_disk_with_CD;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int unzGetGlobalInfo64(unzFile file, unz_global_info64 *pglobal_info)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
const char *comment_ptr = NULL;
|
||||
int32_t err = MZ_OK;
|
||||
|
||||
memset(pglobal_info, 0, sizeof(unz_global_info64));
|
||||
if (compat == NULL)
|
||||
return UNZ_PARAMERROR;
|
||||
err = mz_zip_get_comment(compat->handle, &comment_ptr);
|
||||
if (err == MZ_OK)
|
||||
pglobal_info->size_comment = (uint16_t)strlen(comment_ptr);
|
||||
if ((err == MZ_OK) || (err == MZ_EXIST_ERROR))
|
||||
err = mz_zip_get_number_entry(compat->handle, &pglobal_info->number_entry);
|
||||
if (err == MZ_OK)
|
||||
err = mz_zip_get_disk_number_with_cd(compat->handle, &pglobal_info->number_disk_with_CD);
|
||||
return err;
|
||||
}
|
||||
|
||||
int unzGetGlobalComment(unzFile file, char *comment, uint16_t comment_size)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
const char *comment_ptr = NULL;
|
||||
int32_t err = MZ_OK;
|
||||
|
||||
if (comment == NULL || comment_size == 0)
|
||||
return UNZ_PARAMERROR;
|
||||
err = mz_zip_get_comment(compat->handle, &comment_ptr);
|
||||
if (err == MZ_OK)
|
||||
{
|
||||
strncpy(comment, comment_ptr, comment_size - 1);
|
||||
comment[comment_size - 1] = 0;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int unzOpenCurrentFile3(unzFile file, int *method, int *level, int raw, const char *password)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
mz_zip_file *file_info = NULL;
|
||||
int32_t err = MZ_OK;
|
||||
void *stream = NULL;
|
||||
|
||||
if (compat == NULL)
|
||||
return UNZ_PARAMERROR;
|
||||
if (method != NULL)
|
||||
*method = 0;
|
||||
if (level != NULL)
|
||||
*level = 0;
|
||||
|
||||
compat->total_out = 0;
|
||||
err = mz_zip_entry_read_open(compat->handle, (uint8_t)raw, password);
|
||||
if (err == MZ_OK)
|
||||
err = mz_zip_entry_get_info(compat->handle, &file_info);
|
||||
if (err == MZ_OK)
|
||||
{
|
||||
if (method != NULL)
|
||||
{
|
||||
*method = file_info->compression_method;
|
||||
}
|
||||
|
||||
if (level != NULL)
|
||||
{
|
||||
*level = 6;
|
||||
switch (file_info->flag & 0x06)
|
||||
{
|
||||
case MZ_ZIP_FLAG_DEFLATE_SUPER_FAST:
|
||||
*level = 1;
|
||||
break;
|
||||
case MZ_ZIP_FLAG_DEFLATE_FAST:
|
||||
*level = 2;
|
||||
break;
|
||||
case MZ_ZIP_FLAG_DEFLATE_MAX:
|
||||
*level = 9;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (err == MZ_OK)
|
||||
err = mz_zip_get_stream(compat->handle, &stream);
|
||||
if (err == MZ_OK)
|
||||
compat->entry_pos = mz_stream_tell(stream);
|
||||
return err;
|
||||
}
|
||||
|
||||
int unzOpenCurrentFile(unzFile file)
|
||||
{
|
||||
return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
|
||||
}
|
||||
|
||||
int unzOpenCurrentFilePassword(unzFile file, const char *password)
|
||||
{
|
||||
return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
|
||||
}
|
||||
|
||||
int unzOpenCurrentFile2(unzFile file, int *method, int *level, int raw)
|
||||
{
|
||||
return unzOpenCurrentFile3(file, method, level, raw, NULL);
|
||||
}
|
||||
|
||||
int unzReadCurrentFile(unzFile file, void *buf, uint32_t len)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
int32_t err = MZ_OK;
|
||||
if (compat == NULL || len >= INT32_MAX)
|
||||
return UNZ_PARAMERROR;
|
||||
err = mz_zip_entry_read(compat->handle, buf, (int32_t)len);
|
||||
if (err > 0)
|
||||
compat->total_out += (uint32_t)err;
|
||||
return err;
|
||||
}
|
||||
|
||||
int unzCloseCurrentFile(unzFile file)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
int32_t err = MZ_OK;
|
||||
if (compat == NULL)
|
||||
return UNZ_PARAMERROR;
|
||||
err = mz_zip_entry_close(compat->handle);
|
||||
return err;
|
||||
}
|
||||
|
||||
int unzGetCurrentFileInfo(unzFile file, unz_file_info *pfile_info, char *filename,
|
||||
uint16_t filename_size, void *extrafield, uint16_t extrafield_size, char *comment, uint16_t comment_size)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
mz_zip_file *file_info = NULL;
|
||||
uint16_t bytes_to_copy = 0;
|
||||
int32_t err = MZ_OK;
|
||||
|
||||
if (compat == NULL)
|
||||
return UNZ_PARAMERROR;
|
||||
|
||||
err = mz_zip_entry_get_info(compat->handle, &file_info);
|
||||
|
||||
if ((err == MZ_OK) && (pfile_info != NULL))
|
||||
{
|
||||
pfile_info->version = file_info->version_madeby;
|
||||
pfile_info->version_needed = file_info->version_needed;
|
||||
pfile_info->flag = file_info->flag;
|
||||
pfile_info->compression_method = file_info->compression_method;
|
||||
pfile_info->mz_dos_date = mz_zip_time_t_to_dos_date(file_info->modified_date);
|
||||
//mz_zip_time_t_to_tm(file_info->modified_date, &pfile_info->tmu_date);
|
||||
//pfile_info->tmu_date.tm_year += 1900;
|
||||
pfile_info->crc = file_info->crc;
|
||||
|
||||
pfile_info->size_filename = file_info->filename_size;
|
||||
pfile_info->size_file_extra = file_info->extrafield_size;
|
||||
pfile_info->size_file_comment = file_info->comment_size;
|
||||
|
||||
pfile_info->disk_num_start = (uint16_t)file_info->disk_number;
|
||||
pfile_info->internal_fa = file_info->internal_fa;
|
||||
pfile_info->external_fa = file_info->external_fa;
|
||||
|
||||
pfile_info->compressed_size = (uint32_t)file_info->compressed_size;
|
||||
pfile_info->uncompressed_size = (uint32_t)file_info->uncompressed_size;
|
||||
|
||||
if (filename_size > 0 && filename != NULL && file_info->filename != NULL)
|
||||
{
|
||||
bytes_to_copy = filename_size;
|
||||
if (bytes_to_copy > file_info->filename_size)
|
||||
bytes_to_copy = file_info->filename_size;
|
||||
memcpy(filename, file_info->filename, bytes_to_copy);
|
||||
if (bytes_to_copy < filename_size)
|
||||
filename[bytes_to_copy] = 0;
|
||||
}
|
||||
if (extrafield_size > 0 && extrafield != NULL)
|
||||
{
|
||||
bytes_to_copy = extrafield_size;
|
||||
if (bytes_to_copy > file_info->extrafield_size)
|
||||
bytes_to_copy = file_info->extrafield_size;
|
||||
memcpy(extrafield, file_info->extrafield, bytes_to_copy);
|
||||
}
|
||||
if (comment_size > 0 && comment != NULL && file_info->comment != NULL)
|
||||
{
|
||||
bytes_to_copy = comment_size;
|
||||
if (bytes_to_copy > file_info->comment_size)
|
||||
bytes_to_copy = file_info->comment_size;
|
||||
memcpy(comment, file_info->comment, bytes_to_copy);
|
||||
if (bytes_to_copy < comment_size)
|
||||
comment[bytes_to_copy] = 0;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int unzGetCurrentFileInfo64(unzFile file, unz_file_info64 * pfile_info, char *filename,
|
||||
uint16_t filename_size, void *extrafield, uint16_t extrafield_size, char *comment, uint16_t comment_size)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
mz_zip_file *file_info = NULL;
|
||||
uint16_t bytes_to_copy = 0;
|
||||
int32_t err = MZ_OK;
|
||||
|
||||
if (compat == NULL)
|
||||
return UNZ_PARAMERROR;
|
||||
|
||||
err = mz_zip_entry_get_info(compat->handle, &file_info);
|
||||
|
||||
if ((err == MZ_OK) && (pfile_info != NULL))
|
||||
{
|
||||
pfile_info->version = file_info->version_madeby;
|
||||
pfile_info->version_needed = file_info->version_needed;
|
||||
pfile_info->flag = file_info->flag;
|
||||
pfile_info->compression_method = file_info->compression_method;
|
||||
pfile_info->mz_dos_date = mz_zip_time_t_to_dos_date(file_info->modified_date);
|
||||
//mz_zip_time_t_to_tm(file_info->modified_date, &pfile_info->tmu_date);
|
||||
//pfile_info->tmu_date.tm_year += 1900;
|
||||
pfile_info->crc = file_info->crc;
|
||||
|
||||
pfile_info->size_filename = file_info->filename_size;
|
||||
pfile_info->size_file_extra = file_info->extrafield_size;
|
||||
pfile_info->size_file_comment = file_info->comment_size;
|
||||
|
||||
pfile_info->disk_num_start = file_info->disk_number;
|
||||
pfile_info->internal_fa = file_info->internal_fa;
|
||||
pfile_info->external_fa = file_info->external_fa;
|
||||
|
||||
pfile_info->compressed_size = (uint64_t)file_info->compressed_size;
|
||||
pfile_info->uncompressed_size = (uint64_t)file_info->uncompressed_size;
|
||||
|
||||
if (filename_size > 0 && filename != NULL && file_info->filename != NULL)
|
||||
{
|
||||
bytes_to_copy = filename_size;
|
||||
if (bytes_to_copy > file_info->filename_size)
|
||||
bytes_to_copy = file_info->filename_size;
|
||||
memcpy(filename, file_info->filename, bytes_to_copy);
|
||||
if (bytes_to_copy < filename_size)
|
||||
filename[bytes_to_copy] = 0;
|
||||
}
|
||||
|
||||
if (extrafield_size > 0 && extrafield != NULL)
|
||||
{
|
||||
bytes_to_copy = extrafield_size;
|
||||
if (bytes_to_copy > file_info->extrafield_size)
|
||||
bytes_to_copy = file_info->extrafield_size;
|
||||
memcpy(extrafield, file_info->extrafield, bytes_to_copy);
|
||||
}
|
||||
|
||||
if (comment_size > 0 && comment != NULL && file_info->comment != NULL)
|
||||
{
|
||||
bytes_to_copy = comment_size;
|
||||
if (bytes_to_copy > file_info->comment_size)
|
||||
bytes_to_copy = file_info->comment_size;
|
||||
memcpy(comment, file_info->comment, bytes_to_copy);
|
||||
if (bytes_to_copy < comment_size)
|
||||
comment[bytes_to_copy] = 0;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int unzGoToFirstFile(unzFile file)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
if (compat == NULL)
|
||||
return UNZ_PARAMERROR;
|
||||
compat->entry_index = 0;
|
||||
return mz_zip_goto_first_entry(compat->handle);
|
||||
}
|
||||
|
||||
int unzGoToNextFile(unzFile file)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
int32_t err = MZ_OK;
|
||||
if (compat == NULL)
|
||||
return UNZ_PARAMERROR;
|
||||
err = mz_zip_goto_next_entry(compat->handle);
|
||||
if (err != MZ_END_OF_LIST)
|
||||
compat->entry_index += 1;
|
||||
return err;
|
||||
}
|
||||
|
||||
int unzLocateFile(unzFile file, const char *filename, unzFileNameComparer filename_compare_func)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
mz_zip_file *file_info = NULL;
|
||||
uint64_t preserve_index = 0;
|
||||
int32_t err = MZ_OK;
|
||||
int32_t result = 0;
|
||||
|
||||
if (compat == NULL)
|
||||
return UNZ_PARAMERROR;
|
||||
|
||||
preserve_index = compat->entry_index;
|
||||
|
||||
err = mz_zip_goto_first_entry(compat->handle);
|
||||
while (err == MZ_OK)
|
||||
{
|
||||
err = mz_zip_entry_get_info(compat->handle, &file_info);
|
||||
if (err != MZ_OK)
|
||||
break;
|
||||
|
||||
if (filename_compare_func != NULL)
|
||||
result = filename_compare_func(file, filename, file_info->filename);
|
||||
else
|
||||
result = strcmp(filename, file_info->filename);
|
||||
|
||||
if (result == 0)
|
||||
return MZ_OK;
|
||||
|
||||
err = mz_zip_goto_next_entry(compat->handle);
|
||||
}
|
||||
|
||||
compat->entry_index = preserve_index;
|
||||
return err;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int unzGetFilePos(unzFile file, unz_file_pos *file_pos)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
int32_t offset = 0;
|
||||
|
||||
if (compat == NULL || file_pos == NULL)
|
||||
return UNZ_PARAMERROR;
|
||||
|
||||
offset = unzGetOffset(file);
|
||||
if (offset < 0)
|
||||
return offset;
|
||||
|
||||
file_pos->pos_in_zip_directory = (uint32_t)offset;
|
||||
file_pos->num_of_file = (uint32_t)compat->entry_index;
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int unzGoToFilePos(unzFile file, unz_file_pos *file_pos)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
unz64_file_pos file_pos64;
|
||||
|
||||
if (compat == NULL || file_pos == NULL)
|
||||
return UNZ_PARAMERROR;
|
||||
|
||||
file_pos64.pos_in_zip_directory = file_pos->pos_in_zip_directory;
|
||||
file_pos64.num_of_file = file_pos->num_of_file;
|
||||
|
||||
return unzGoToFilePos64(file, &file_pos64);
|
||||
}
|
||||
|
||||
int unzGetFilePos64(unzFile file, unz64_file_pos *file_pos)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
int64_t offset = 0;
|
||||
|
||||
if (compat == NULL || file_pos == NULL)
|
||||
return UNZ_PARAMERROR;
|
||||
|
||||
offset = unzGetOffset64(file);
|
||||
if (offset < 0)
|
||||
return (int)offset;
|
||||
|
||||
file_pos->pos_in_zip_directory = offset;
|
||||
file_pos->num_of_file = compat->entry_index;
|
||||
return UNZ_OK;
|
||||
}
|
||||
|
||||
int unzGoToFilePos64(unzFile file, const unz64_file_pos *file_pos)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
int32_t err = MZ_OK;
|
||||
|
||||
if (compat == NULL || file_pos == NULL)
|
||||
return UNZ_PARAMERROR;
|
||||
|
||||
err = mz_zip_goto_entry(compat->handle, file_pos->pos_in_zip_directory);
|
||||
if (err == MZ_OK)
|
||||
compat->entry_index = file_pos->num_of_file;
|
||||
return err;
|
||||
}
|
||||
|
||||
int32_t unzGetOffset(unzFile file)
|
||||
{
|
||||
return (int32_t)unzGetOffset64(file);
|
||||
}
|
||||
|
||||
int64_t unzGetOffset64(unzFile file)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
if (compat == NULL)
|
||||
return UNZ_PARAMERROR;
|
||||
return mz_zip_get_entry(compat->handle);
|
||||
}
|
||||
|
||||
int unzSetOffset(unzFile file, uint32_t pos)
|
||||
{
|
||||
return unzSetOffset64(file, pos);
|
||||
}
|
||||
|
||||
int unzSetOffset64(unzFile file, int64_t pos)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
if (compat == NULL)
|
||||
return UNZ_PARAMERROR;
|
||||
return (int)mz_zip_goto_entry(compat->handle, pos);
|
||||
}
|
||||
|
||||
int unzGetLocalExtrafield(unzFile file, void *buf, unsigned int len)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
mz_zip_file *file_info = NULL;
|
||||
int32_t err = MZ_OK;
|
||||
int32_t bytes_to_copy = 0;
|
||||
|
||||
if (compat == NULL || buf == NULL || len >= INT32_MAX)
|
||||
return UNZ_PARAMERROR;
|
||||
|
||||
err = mz_zip_entry_get_local_info(compat->handle, &file_info);
|
||||
if (err != MZ_OK)
|
||||
return err;
|
||||
|
||||
bytes_to_copy = (int32_t)len;
|
||||
if (bytes_to_copy > file_info->extrafield_size)
|
||||
bytes_to_copy = file_info->extrafield_size;
|
||||
|
||||
memcpy(buf, file_info->extrafield, bytes_to_copy);
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int64_t unztell(unzFile file)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
if (compat == NULL)
|
||||
return UNZ_PARAMERROR;
|
||||
return (int64_t)compat->total_out;
|
||||
}
|
||||
|
||||
int32_t unzTell(unzFile file)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
if (compat == NULL)
|
||||
return UNZ_PARAMERROR;
|
||||
return (int32_t)compat->total_out;
|
||||
}
|
||||
|
||||
int64_t unzTell64(unzFile file)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
if (compat == NULL)
|
||||
return UNZ_PARAMERROR;
|
||||
return (int64_t)compat->total_out;
|
||||
}
|
||||
|
||||
int unzSeek(unzFile file, int32_t offset, int origin)
|
||||
{
|
||||
return unzSeek64(file, offset, origin);
|
||||
}
|
||||
|
||||
int unzSeek64(unzFile file, int64_t offset, int origin)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
mz_zip_file *file_info = NULL;
|
||||
int64_t position = 0;
|
||||
int32_t err = MZ_OK;
|
||||
void *stream = NULL;
|
||||
|
||||
if (compat == NULL)
|
||||
return UNZ_PARAMERROR;
|
||||
err = mz_zip_entry_get_info(compat->handle, &file_info);
|
||||
if (err != MZ_OK)
|
||||
return err;
|
||||
if (file_info->compression_method != MZ_COMPRESS_METHOD_STORE)
|
||||
return UNZ_ERRNO;
|
||||
|
||||
if (origin == SEEK_SET)
|
||||
position = offset;
|
||||
else if (origin == SEEK_CUR)
|
||||
position = compat->total_out + offset;
|
||||
else if (origin == SEEK_END)
|
||||
position = (int64_t)file_info->compressed_size + offset;
|
||||
else
|
||||
return UNZ_PARAMERROR;
|
||||
|
||||
if (position > (int64_t)file_info->compressed_size)
|
||||
return UNZ_PARAMERROR;
|
||||
|
||||
err = mz_zip_get_stream(compat->handle, &stream);
|
||||
if (err == MZ_OK)
|
||||
err = mz_stream_seek(stream, compat->entry_pos + position, MZ_SEEK_SET);
|
||||
if (err == MZ_OK)
|
||||
compat->total_out = position;
|
||||
return err;
|
||||
}
|
||||
|
||||
int unzEndOfFile(unzFile file)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
mz_zip_file *file_info = NULL;
|
||||
int32_t err = MZ_OK;
|
||||
|
||||
if (compat == NULL)
|
||||
return UNZ_PARAMERROR;
|
||||
err = mz_zip_entry_get_info(compat->handle, &file_info);
|
||||
if (err != MZ_OK)
|
||||
return err;
|
||||
if (compat->total_out == (int64_t)file_info->uncompressed_size)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* unzGetStream(unzFile file)
|
||||
{
|
||||
mz_compat *compat = (mz_compat *)file;
|
||||
if (compat == NULL)
|
||||
return NULL;
|
||||
return (void *)compat->stream;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
void fill_fopen_filefunc(zlib_filefunc_def *pzlib_filefunc_def)
|
||||
{
|
||||
if (pzlib_filefunc_def != NULL)
|
||||
*pzlib_filefunc_def = mz_stream_os_get_interface();
|
||||
}
|
||||
|
||||
void fill_fopen64_filefunc(zlib_filefunc64_def *pzlib_filefunc_def)
|
||||
{
|
||||
if (pzlib_filefunc_def != NULL)
|
||||
*pzlib_filefunc_def = mz_stream_os_get_interface();
|
||||
}
|
||||
|
||||
void fill_win32_filefunc(zlib_filefunc_def *pzlib_filefunc_def)
|
||||
{
|
||||
if (pzlib_filefunc_def != NULL)
|
||||
*pzlib_filefunc_def = mz_stream_os_get_interface();
|
||||
}
|
||||
|
||||
void fill_win32_filefunc64(zlib_filefunc64_def *pzlib_filefunc_def)
|
||||
{
|
||||
if (pzlib_filefunc_def != NULL)
|
||||
*pzlib_filefunc_def = mz_stream_os_get_interface();
|
||||
}
|
||||
|
||||
void fill_win32_filefunc64A(zlib_filefunc64_def *pzlib_filefunc_def)
|
||||
{
|
||||
if (pzlib_filefunc_def != NULL)
|
||||
*pzlib_filefunc_def = mz_stream_os_get_interface();
|
||||
}
|
||||
|
||||
void fill_win32_filefunc64W(zlib_filefunc64_def *pzlib_filefunc_def)
|
||||
{
|
||||
/* NOTE: You should no longer pass in widechar string to open function */
|
||||
if (pzlib_filefunc_def != NULL)
|
||||
*pzlib_filefunc_def = mz_stream_os_get_interface();
|
||||
}
|
||||
|
||||
void fill_memory_filefunc(zlib_filefunc_def *pzlib_filefunc_def)
|
||||
{
|
||||
if (pzlib_filefunc_def != NULL)
|
||||
*pzlib_filefunc_def = mz_stream_mem_get_interface();
|
||||
}
|
250
third-party/ZipArchive/Sources/minizip/mz_compat.h
vendored
Normal file
250
third-party/ZipArchive/Sources/minizip/mz_compat.h
vendored
Normal file
@ -0,0 +1,250 @@
|
||||
/* mz_compat.h -- Backwards compatible interface for older versions
|
||||
Version 2.8.6, April 8, 2019
|
||||
part of the MiniZip project
|
||||
|
||||
Copyright (C) 2010-2019 Nathan Moinvaziri
|
||||
https://github.com/nmoinvaz/minizip
|
||||
Copyright (C) 1998-2010 Gilles Vollant
|
||||
https://www.winimage.com/zLibDll/minizip.html
|
||||
|
||||
This program is distributed under the terms of the same license as zlib.
|
||||
See the accompanying LICENSE file for the full text of the license.
|
||||
*/
|
||||
|
||||
#ifndef MZ_COMPAT_H
|
||||
#define MZ_COMPAT_H
|
||||
|
||||
#include "mz.h"
|
||||
#include <ZipArchive/SSZipCommon.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#if defined(HAVE_ZLIB) && defined(MAX_MEM_LEVEL)
|
||||
#ifndef DEF_MEM_LEVEL
|
||||
# if MAX_MEM_LEVEL >= 8
|
||||
# define DEF_MEM_LEVEL 8
|
||||
# else
|
||||
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
|
||||
# endif
|
||||
#endif
|
||||
#endif
|
||||
#ifndef MAX_WBITS
|
||||
#define MAX_WBITS 15
|
||||
#endif
|
||||
#ifndef DEF_MEM_LEVEL
|
||||
#define DEF_MEM_LEVEL 8
|
||||
#endif
|
||||
|
||||
#ifndef ZEXPORT
|
||||
# define ZEXPORT MZ_EXPORT
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#if defined(STRICTZIP) || defined(STRICTZIPUNZIP)
|
||||
/* like the STRICT of WIN32, we define a pointer that cannot be converted
|
||||
from (void*) without cast */
|
||||
typedef struct TagzipFile__ { int unused; } zip_file__;
|
||||
typedef zip_file__ *zipFile;
|
||||
#else
|
||||
typedef void *zipFile;
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
typedef void *zlib_filefunc_def;
|
||||
typedef void *zlib_filefunc64_def;
|
||||
typedef const char *zipcharpc;
|
||||
|
||||
typedef struct tm tm_unz;
|
||||
typedef struct tm tm_zip;
|
||||
|
||||
typedef uint64_t ZPOS64_T;
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
// ZipArchive 2.x uses dos_date
|
||||
#define MZ_COMPAT_VERSION 120
|
||||
|
||||
#if MZ_COMPAT_VERSION <= 110
|
||||
#define mz_dos_date dosDate
|
||||
#else
|
||||
#define mz_dos_date dos_date
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t mz_dos_date;
|
||||
struct tm tmz_date;
|
||||
uint16_t internal_fa; /* internal file attributes 2 bytes */
|
||||
uint32_t external_fa; /* external file attributes 4 bytes */
|
||||
} zip_fileinfo;
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#define ZIP_OK (0)
|
||||
#define ZIP_EOF (0)
|
||||
#define ZIP_ERRNO (-1)
|
||||
#define ZIP_PARAMERROR (-102)
|
||||
#define ZIP_BADZIPFILE (-103)
|
||||
#define ZIP_INTERNALERROR (-104)
|
||||
|
||||
#define Z_BZIP2ED (12)
|
||||
|
||||
#define APPEND_STATUS_CREATE (0)
|
||||
#define APPEND_STATUS_CREATEAFTER (1)
|
||||
#define APPEND_STATUS_ADDINZIP (2)
|
||||
|
||||
/***************************************************************************/
|
||||
/* Writing a zip file */
|
||||
|
||||
ZEXPORT zipFile zipOpen(const char *path, int append);
|
||||
ZEXPORT zipFile zipOpen64(const void *path, int append);
|
||||
ZEXPORT zipFile zipOpen2(const char *path, int append, const char **globalcomment,
|
||||
zlib_filefunc_def *pzlib_filefunc_def);
|
||||
ZEXPORT zipFile zipOpen2_64(const void *path, int append, const char **globalcomment,
|
||||
zlib_filefunc64_def *pzlib_filefunc_def);
|
||||
zipFile zipOpen_MZ(void *stream, int append, const char **globalcomment);
|
||||
|
||||
ZEXPORT int zipOpenNewFileInZip5(zipFile file, const char *filename, const zip_fileinfo *zipfi,
|
||||
const void *extrafield_local, uint16_t size_extrafield_local, const void *extrafield_global,
|
||||
uint16_t size_extrafield_global, const char *comment, uint16_t compression_method, int level,
|
||||
int raw, int windowBits, int memLevel, int strategy, const char *password,
|
||||
signed char aes, uint16_t version_madeby, uint16_t flag_base, int zip64);
|
||||
|
||||
ZEXPORT int zipWriteInFileInZip(zipFile file, const void *buf, uint32_t len);
|
||||
|
||||
ZEXPORT int zipCloseFileInZipRaw(zipFile file, uint32_t uncompressed_size, uint32_t crc32);
|
||||
ZEXPORT int zipCloseFileInZipRaw64(zipFile file, int64_t uncompressed_size, uint32_t crc32);
|
||||
ZEXPORT int zipCloseFileInZip(zipFile file);
|
||||
ZEXPORT int zipCloseFileInZip64(zipFile file);
|
||||
|
||||
ZEXPORT int zipClose(zipFile file, const char *global_comment);
|
||||
ZEXPORT int zipClose_64(zipFile file, const char *global_comment);
|
||||
ZEXPORT int zipClose2_64(zipFile file, const char *global_comment, uint16_t version_madeby);
|
||||
int zipClose_MZ(zipFile file, const char *global_comment);
|
||||
int zipClose2_MZ(zipFile file, const char *global_comment, uint16_t version_madeby);
|
||||
ZEXPORT void* zipGetStream(zipFile file);
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
|
||||
/* like the STRICT of WIN32, we define a pointer that cannot be converted
|
||||
from (void*) without cast */
|
||||
typedef struct TagunzFile__ { int unused; } unz_file__;
|
||||
typedef unz_file__ *unzFile;
|
||||
#else
|
||||
typedef void *unzFile;
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#define UNZ_OK (0)
|
||||
#define UNZ_END_OF_LIST_OF_FILE (-100)
|
||||
#define UNZ_ERRNO (-1)
|
||||
#define UNZ_EOF (0)
|
||||
#define UNZ_PARAMERROR (-102)
|
||||
#define UNZ_BADZIPFILE (-103)
|
||||
#define UNZ_INTERNALERROR (-104)
|
||||
#define UNZ_CRCERROR (-105)
|
||||
#define UNZ_BADPASSWORD (-106)
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
typedef int (*unzFileNameComparer)(unzFile file, const char *filename1, const char *filename2);
|
||||
typedef int (*unzIteratorFunction)(unzFile file);
|
||||
typedef int (*unzIteratorFunction2)(unzFile file, unz_file_info64 *pfile_info, char *filename,
|
||||
uint16_t filename_size, void *extrafield, uint16_t extrafield_size, char *comment,
|
||||
uint16_t comment_size);
|
||||
|
||||
/***************************************************************************/
|
||||
/* Reading a zip file */
|
||||
|
||||
ZEXPORT unzFile unzOpen(const char *path);
|
||||
ZEXPORT unzFile unzOpen64(const void *path);
|
||||
ZEXPORT unzFile unzOpen2(const char *path, zlib_filefunc_def *pzlib_filefunc_def);
|
||||
ZEXPORT unzFile unzOpen2_64(const void *path, zlib_filefunc64_def *pzlib_filefunc_def);
|
||||
unzFile unzOpen_MZ(void *stream);
|
||||
|
||||
ZEXPORT int unzClose(unzFile file);
|
||||
int unzClose_MZ(unzFile file);
|
||||
|
||||
ZEXPORT int unzGetGlobalInfo(unzFile file, unz_global_info* pglobal_info32);
|
||||
ZEXPORT int unzGetGlobalInfo64(unzFile file, unz_global_info64 *pglobal_info);
|
||||
ZEXPORT int unzGetGlobalComment(unzFile file, char *comment, uint16_t comment_size);
|
||||
|
||||
ZEXPORT int unzOpenCurrentFile(unzFile file);
|
||||
ZEXPORT int unzOpenCurrentFilePassword(unzFile file, const char *password);
|
||||
ZEXPORT int unzOpenCurrentFile2(unzFile file, int *method, int *level, int raw);
|
||||
ZEXPORT int unzOpenCurrentFile3(unzFile file, int *method, int *level, int raw, const char *password);
|
||||
ZEXPORT int unzReadCurrentFile(unzFile file, void *buf, uint32_t len);
|
||||
ZEXPORT int unzCloseCurrentFile(unzFile file);
|
||||
|
||||
|
||||
ZEXPORT int unzGetCurrentFileInfo(unzFile file, unz_file_info *pfile_info, char *filename,
|
||||
uint16_t filename_size, void *extrafield, uint16_t extrafield_size, char *comment,
|
||||
uint16_t comment_size);
|
||||
ZEXPORT int unzGetCurrentFileInfo64(unzFile file, unz_file_info64 * pfile_info, char *filename,
|
||||
uint16_t filename_size, void *extrafield, uint16_t extrafield_size, char *comment,
|
||||
uint16_t comment_size);
|
||||
|
||||
ZEXPORT int unzGoToFirstFile(unzFile file);
|
||||
ZEXPORT int unzGoToNextFile(unzFile file);
|
||||
ZEXPORT int unzLocateFile(unzFile file, const char *filename, unzFileNameComparer filename_compare_func);
|
||||
|
||||
ZEXPORT int unzGetLocalExtrafield(unzFile file, void *buf, unsigned int len);
|
||||
|
||||
/***************************************************************************/
|
||||
/* Raw access to zip file */
|
||||
|
||||
typedef struct unz_file_pos_s
|
||||
{
|
||||
uint32_t pos_in_zip_directory; /* offset in zip file directory */
|
||||
uint32_t num_of_file; /* # of file */
|
||||
} unz_file_pos;
|
||||
|
||||
ZEXPORT int unzGetFilePos(unzFile file, unz_file_pos *file_pos);
|
||||
ZEXPORT int unzGoToFilePos(unzFile file, unz_file_pos *file_pos);
|
||||
|
||||
typedef struct unz64_file_pos_s
|
||||
{
|
||||
int64_t pos_in_zip_directory; /* offset in zip file directory */
|
||||
uint64_t num_of_file; /* # of file */
|
||||
} unz64_file_pos;
|
||||
|
||||
ZEXPORT int unzGetFilePos64(unzFile file, unz64_file_pos *file_pos);
|
||||
ZEXPORT int unzGoToFilePos64(unzFile file, const unz64_file_pos *file_pos);
|
||||
|
||||
ZEXPORT int64_t unzGetOffset64(unzFile file);
|
||||
ZEXPORT int32_t unzGetOffset(unzFile file);
|
||||
ZEXPORT int unzSetOffset64(unzFile file, int64_t pos);
|
||||
ZEXPORT int unzSetOffset(unzFile file, uint32_t pos);
|
||||
ZEXPORT int64_t unztell(unzFile file);
|
||||
ZEXPORT int32_t unzTell(unzFile file);
|
||||
ZEXPORT int64_t unzTell64(unzFile file);
|
||||
ZEXPORT int unzSeek(unzFile file, int32_t offset, int origin);
|
||||
ZEXPORT int unzSeek64(unzFile file, int64_t offset, int origin);
|
||||
ZEXPORT int unzEndOfFile(unzFile file);
|
||||
ZEXPORT void* unzGetStream(unzFile file);
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
ZEXPORT void fill_fopen_filefunc(zlib_filefunc_def *pzlib_filefunc_def);
|
||||
ZEXPORT void fill_fopen64_filefunc(zlib_filefunc64_def *pzlib_filefunc_def);
|
||||
ZEXPORT void fill_win32_filefunc(zlib_filefunc_def *pzlib_filefunc_def);
|
||||
ZEXPORT void fill_win32_filefunc64(zlib_filefunc64_def *pzlib_filefunc_def);
|
||||
ZEXPORT void fill_win32_filefunc64A(zlib_filefunc64_def *pzlib_filefunc_def);
|
||||
ZEXPORT void fill_win32_filefunc64W(zlib_filefunc64_def *pzlib_filefunc_def);
|
||||
ZEXPORT void fill_memory_filefunc(zlib_filefunc_def *pzlib_filefunc_def);
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
195
third-party/ZipArchive/Sources/minizip/mz_crypt.c
vendored
Normal file
195
third-party/ZipArchive/Sources/minizip/mz_crypt.c
vendored
Normal file
@ -0,0 +1,195 @@
|
||||
/* mz_crypt.c -- Crypto/hash functions
|
||||
Version 2.9.2, February 12, 2020
|
||||
part of the MiniZip project
|
||||
|
||||
Copyright (C) 2010-2020 Nathan Moinvaziri
|
||||
https://github.com/nmoinvaz/minizip
|
||||
|
||||
This program is distributed under the terms of the same license as zlib.
|
||||
See the accompanying LICENSE file for the full text of the license.
|
||||
*/
|
||||
|
||||
|
||||
#include "mz.h"
|
||||
#include "mz_crypt.h"
|
||||
|
||||
#if defined(HAVE_ZLIB)
|
||||
# include "zlib.h"
|
||||
# if defined(ZLIBNG_VERNUM) && !defined(ZLIB_COMPAT)
|
||||
# include "zlib-ng.h"
|
||||
# endif
|
||||
#elif defined(HAVE_LZMA)
|
||||
# include "lzma.h"
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
/* Define z_crc_t in zlib 1.2.5 and less or if using zlib-ng */
|
||||
|
||||
#if defined(HAVE_ZLIB) && defined(ZLIBNG_VERNUM)
|
||||
# if defined(ZLIB_COMPAT)
|
||||
# define ZLIB_PREFIX(x) x
|
||||
# else
|
||||
# define ZLIB_PREFIX(x) zng_ ## x
|
||||
# endif
|
||||
typedef uint32_t z_crc_t;
|
||||
#elif defined(HAVE_ZLIB)
|
||||
# define ZLIB_PREFIX(x) x
|
||||
# if (ZLIB_VERNUM < 0x1270)
|
||||
typedef unsigned long z_crc_t;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
uint32_t mz_crypt_crc32_update(uint32_t value, const uint8_t *buf, int32_t size)
|
||||
{
|
||||
#if defined(HAVE_ZLIB)
|
||||
return (uint32_t)ZLIB_PREFIX(crc32)((z_crc_t)value, buf, (uInt)size);
|
||||
#elif defined(HAVE_LZMA)
|
||||
return (uint32_t)lzma_crc32(buf, (size_t)size, (uint32_t)value);
|
||||
#else
|
||||
static uint32_t crc32_table[256] = {
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
||||
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
||||
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
||||
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
|
||||
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
||||
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
|
||||
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
|
||||
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
|
||||
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
|
||||
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
||||
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
|
||||
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
||||
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
||||
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
|
||||
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
|
||||
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
||||
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
|
||||
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
||||
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
|
||||
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
||||
};
|
||||
value = ~value;
|
||||
|
||||
while (size > 0)
|
||||
{
|
||||
value = (value >> 8) ^ crc32_table[(value ^ *buf) & 0xFF];
|
||||
|
||||
buf += 1;
|
||||
size -= 1;
|
||||
}
|
||||
|
||||
return ~value;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef MZ_ZIP_NO_ENCRYPTION
|
||||
int32_t mz_crypt_pbkdf2(uint8_t *password, int32_t password_length, uint8_t *salt,
|
||||
int32_t salt_length, int32_t iteration_count, uint8_t *key, int32_t key_length)
|
||||
{
|
||||
void *hmac1 = NULL;
|
||||
void *hmac2 = NULL;
|
||||
void *hmac3 = NULL;
|
||||
int32_t err = MZ_OK;
|
||||
uint16_t i = 0;
|
||||
uint16_t j = 0;
|
||||
uint16_t k = 0;
|
||||
uint16_t block_count = 0;
|
||||
uint8_t uu[MZ_HASH_SHA1_SIZE];
|
||||
uint8_t ux[MZ_HASH_SHA1_SIZE];
|
||||
|
||||
if (password == NULL || salt == NULL || key == NULL)
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
memset(key, 0, key_length);
|
||||
|
||||
mz_crypt_hmac_create(&hmac1);
|
||||
mz_crypt_hmac_create(&hmac2);
|
||||
mz_crypt_hmac_create(&hmac3);
|
||||
|
||||
mz_crypt_hmac_set_algorithm(hmac1, MZ_HASH_SHA1);
|
||||
mz_crypt_hmac_set_algorithm(hmac2, MZ_HASH_SHA1);
|
||||
mz_crypt_hmac_set_algorithm(hmac3, MZ_HASH_SHA1);
|
||||
|
||||
err = mz_crypt_hmac_init(hmac1, password, password_length);
|
||||
if (err == MZ_OK)
|
||||
err = mz_crypt_hmac_init(hmac2, password, password_length);
|
||||
if (err == MZ_OK)
|
||||
err = mz_crypt_hmac_update(hmac2, salt, salt_length);
|
||||
|
||||
block_count = 1 + ((uint16_t)key_length - 1) / MZ_HASH_SHA1_SIZE;
|
||||
|
||||
for (i = 0; (err == MZ_OK) && (i < block_count); i += 1)
|
||||
{
|
||||
memset(ux, 0, sizeof(ux));
|
||||
|
||||
err = mz_crypt_hmac_copy(hmac2, hmac3);
|
||||
if (err != MZ_OK)
|
||||
break;
|
||||
|
||||
uu[0] = (uint8_t)((i + 1) >> 24);
|
||||
uu[1] = (uint8_t)((i + 1) >> 16);
|
||||
uu[2] = (uint8_t)((i + 1) >> 8);
|
||||
uu[3] = (uint8_t)(i + 1);
|
||||
|
||||
for (j = 0, k = 4; j < iteration_count; j += 1)
|
||||
{
|
||||
err = mz_crypt_hmac_update(hmac3, uu, k);
|
||||
if (err == MZ_OK)
|
||||
err = mz_crypt_hmac_end(hmac3, uu, sizeof(uu));
|
||||
if (err != MZ_OK)
|
||||
break;
|
||||
|
||||
for(k = 0; k < MZ_HASH_SHA1_SIZE; k += 1)
|
||||
ux[k] ^= uu[k];
|
||||
|
||||
err = mz_crypt_hmac_copy(hmac1, hmac3);
|
||||
if (err != MZ_OK)
|
||||
break;
|
||||
}
|
||||
|
||||
if (err != MZ_OK)
|
||||
break;
|
||||
|
||||
j = 0;
|
||||
k = i * MZ_HASH_SHA1_SIZE;
|
||||
|
||||
while (j < MZ_HASH_SHA1_SIZE && k < key_length)
|
||||
key[k++] = ux[j++];
|
||||
}
|
||||
|
||||
/* hmac3 uses the same provider as hmac2, so it must be deleted
|
||||
before the context is destroyed. */
|
||||
mz_crypt_hmac_delete(&hmac3);
|
||||
mz_crypt_hmac_delete(&hmac1);
|
||||
mz_crypt_hmac_delete(&hmac2);
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
66
third-party/ZipArchive/Sources/minizip/mz_crypt.h
vendored
Normal file
66
third-party/ZipArchive/Sources/minizip/mz_crypt.h
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
/* mz_crypt.h -- Crypto/hash functions
|
||||
Version 2.9.2, February 12, 2020
|
||||
part of the MiniZip project
|
||||
|
||||
Copyright (C) 2010-2020 Nathan Moinvaziri
|
||||
https://github.com/nmoinvaz/minizip
|
||||
|
||||
This program is distributed under the terms of the same license as zlib.
|
||||
See the accompanying LICENSE file for the full text of the license.
|
||||
*/
|
||||
|
||||
#ifndef MZ_CRYPT_H
|
||||
#define MZ_CRYPT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
uint32_t mz_crypt_crc32_update(uint32_t value, const uint8_t *buf, int32_t size);
|
||||
|
||||
int32_t mz_crypt_pbkdf2(uint8_t *password, int32_t password_length, uint8_t *salt,
|
||||
int32_t salt_length, int32_t iteration_count, uint8_t *key, int32_t key_length);
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_crypt_rand(uint8_t *buf, int32_t size);
|
||||
|
||||
void mz_crypt_sha_reset(void *handle);
|
||||
int32_t mz_crypt_sha_begin(void *handle);
|
||||
int32_t mz_crypt_sha_update(void *handle, const void *buf, int32_t size);
|
||||
int32_t mz_crypt_sha_end(void *handle, uint8_t *digest, int32_t digest_size);
|
||||
void mz_crypt_sha_set_algorithm(void *handle, uint16_t algorithm);
|
||||
void* mz_crypt_sha_create(void **handle);
|
||||
void mz_crypt_sha_delete(void **handle);
|
||||
|
||||
void mz_crypt_aes_reset(void *handle);
|
||||
int32_t mz_crypt_aes_encrypt(void *handle, uint8_t *buf, int32_t size);
|
||||
int32_t mz_crypt_aes_decrypt(void *handle, uint8_t *buf, int32_t size);
|
||||
int32_t mz_crypt_aes_set_encrypt_key(void *handle, const void *key, int32_t key_length);
|
||||
int32_t mz_crypt_aes_set_decrypt_key(void *handle, const void *key, int32_t key_length);
|
||||
void mz_crypt_aes_set_mode(void *handle, int32_t mode);
|
||||
void* mz_crypt_aes_create(void **handle);
|
||||
void mz_crypt_aes_delete(void **handle);
|
||||
|
||||
void mz_crypt_hmac_reset(void *handle);
|
||||
int32_t mz_crypt_hmac_init(void *handle, const void *key, int32_t key_length);
|
||||
int32_t mz_crypt_hmac_update(void *handle, const void *buf, int32_t size);
|
||||
int32_t mz_crypt_hmac_end(void *handle, uint8_t *digest, int32_t digest_size);
|
||||
int32_t mz_crypt_hmac_copy(void *src_handle, void *target_handle);
|
||||
void mz_crypt_hmac_set_algorithm(void *handle, uint16_t algorithm);
|
||||
void* mz_crypt_hmac_create(void **handle);
|
||||
void mz_crypt_hmac_delete(void **handle);
|
||||
|
||||
int32_t mz_crypt_sign(uint8_t *message, int32_t message_size, uint8_t *cert_data, int32_t cert_data_size,
|
||||
const char *cert_pwd, uint8_t **signature, int32_t *signature_size);
|
||||
int32_t mz_crypt_sign_verify(uint8_t *message, int32_t message_size, uint8_t *signature, int32_t signature_size);
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
532
third-party/ZipArchive/Sources/minizip/mz_crypt_apple.c
vendored
Normal file
532
third-party/ZipArchive/Sources/minizip/mz_crypt_apple.c
vendored
Normal file
@ -0,0 +1,532 @@
|
||||
/* mz_crypt_apple.c -- Crypto/hash functions for Apple
|
||||
Version 2.9.2, February 12, 2020
|
||||
part of the MiniZip project
|
||||
|
||||
Copyright (C) 2010-2020 Nathan Moinvaziri
|
||||
https://github.com/nmoinvaz/minizip
|
||||
|
||||
This program is distributed under the terms of the same license as zlib.
|
||||
See the accompanying LICENSE file for the full text of the license.
|
||||
*/
|
||||
|
||||
|
||||
#include "mz.h"
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <CommonCrypto/CommonCryptor.h>
|
||||
#include <CommonCrypto/CommonDigest.h>
|
||||
#include <CommonCrypto/CommonHMAC.h>
|
||||
#include <Security/Security.h>
|
||||
#include <Security/SecPolicy.h>
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_crypt_rand(uint8_t *buf, int32_t size)
|
||||
{
|
||||
if (SecRandomCopyBytes(kSecRandomDefault, size, buf) != errSecSuccess)
|
||||
return 0;
|
||||
return size;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
typedef struct mz_crypt_sha_s {
|
||||
CC_SHA1_CTX ctx1;
|
||||
CC_SHA256_CTX ctx256;
|
||||
int32_t error;
|
||||
int32_t initialized;
|
||||
uint16_t algorithm;
|
||||
} mz_crypt_sha;
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
void mz_crypt_sha_reset(void *handle)
|
||||
{
|
||||
mz_crypt_sha *sha = (mz_crypt_sha *)handle;
|
||||
|
||||
sha->error = 0;
|
||||
sha->initialized = 0;
|
||||
}
|
||||
|
||||
int32_t mz_crypt_sha_begin(void *handle)
|
||||
{
|
||||
mz_crypt_sha *sha = (mz_crypt_sha *)handle;
|
||||
|
||||
if (sha == NULL)
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
mz_crypt_sha_reset(handle);
|
||||
|
||||
if (sha->algorithm == MZ_HASH_SHA1)
|
||||
sha->error = CC_SHA1_Init(&sha->ctx1);
|
||||
else if (sha->algorithm == MZ_HASH_SHA256)
|
||||
sha->error = CC_SHA256_Init(&sha->ctx256);
|
||||
else
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
if (!sha->error)
|
||||
return MZ_HASH_ERROR;
|
||||
|
||||
sha->initialized = 1;
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_crypt_sha_update(void *handle, const void *buf, int32_t size)
|
||||
{
|
||||
mz_crypt_sha *sha = (mz_crypt_sha *)handle;
|
||||
|
||||
if (sha == NULL || buf == NULL || !sha->initialized)
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
if (sha->algorithm == MZ_HASH_SHA1)
|
||||
sha->error = CC_SHA1_Update(&sha->ctx1, buf, size);
|
||||
else
|
||||
sha->error = CC_SHA256_Update(&sha->ctx256, buf, size);
|
||||
|
||||
if (!sha->error)
|
||||
return MZ_HASH_ERROR;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int32_t mz_crypt_sha_end(void *handle, uint8_t *digest, int32_t digest_size)
|
||||
{
|
||||
mz_crypt_sha *sha = (mz_crypt_sha *)handle;
|
||||
|
||||
if (sha == NULL || digest == NULL || !sha->initialized)
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
if (sha->algorithm == MZ_HASH_SHA1)
|
||||
{
|
||||
if (digest_size < MZ_HASH_SHA1_SIZE)
|
||||
return MZ_BUF_ERROR;
|
||||
sha->error = CC_SHA1_Final(digest, &sha->ctx1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (digest_size < MZ_HASH_SHA256_SIZE)
|
||||
return MZ_BUF_ERROR;
|
||||
sha->error = CC_SHA256_Final(digest, &sha->ctx256);
|
||||
}
|
||||
|
||||
if (!sha->error)
|
||||
return MZ_HASH_ERROR;
|
||||
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
void mz_crypt_sha_set_algorithm(void *handle, uint16_t algorithm)
|
||||
{
|
||||
mz_crypt_sha *sha = (mz_crypt_sha *)handle;
|
||||
sha->algorithm = algorithm;
|
||||
}
|
||||
|
||||
void *mz_crypt_sha_create(void **handle)
|
||||
{
|
||||
mz_crypt_sha *sha = NULL;
|
||||
|
||||
sha = (mz_crypt_sha *)MZ_ALLOC(sizeof(mz_crypt_sha));
|
||||
if (sha != NULL)
|
||||
{
|
||||
memset(sha, 0, sizeof(mz_crypt_sha));
|
||||
sha->algorithm = MZ_HASH_SHA256;
|
||||
}
|
||||
if (handle != NULL)
|
||||
*handle = sha;
|
||||
|
||||
return sha;
|
||||
}
|
||||
|
||||
void mz_crypt_sha_delete(void **handle)
|
||||
{
|
||||
mz_crypt_sha *sha = NULL;
|
||||
if (handle == NULL)
|
||||
return;
|
||||
sha = (mz_crypt_sha *)*handle;
|
||||
if (sha != NULL)
|
||||
{
|
||||
mz_crypt_sha_reset(*handle);
|
||||
MZ_FREE(sha);
|
||||
}
|
||||
*handle = NULL;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
typedef struct mz_crypt_aes_s {
|
||||
CCCryptorRef crypt;
|
||||
int32_t mode;
|
||||
int32_t error;
|
||||
} mz_crypt_aes;
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
void mz_crypt_aes_reset(void *handle)
|
||||
{
|
||||
mz_crypt_aes *aes = (mz_crypt_aes *)handle;
|
||||
|
||||
if (aes->crypt != NULL)
|
||||
CCCryptorRelease(aes->crypt);
|
||||
aes->crypt = NULL;
|
||||
}
|
||||
|
||||
int32_t mz_crypt_aes_encrypt(void *handle, uint8_t *buf, int32_t size)
|
||||
{
|
||||
mz_crypt_aes *aes = (mz_crypt_aes *)handle;
|
||||
size_t data_moved = 0;
|
||||
|
||||
if (aes == NULL || buf == NULL)
|
||||
return MZ_PARAM_ERROR;
|
||||
if (size != MZ_AES_BLOCK_SIZE)
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
aes->error = CCCryptorUpdate(aes->crypt, buf, size, buf, size, &data_moved);
|
||||
|
||||
if (aes->error != kCCSuccess)
|
||||
return MZ_HASH_ERROR;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int32_t mz_crypt_aes_decrypt(void *handle, uint8_t *buf, int32_t size)
|
||||
{
|
||||
mz_crypt_aes *aes = (mz_crypt_aes *)handle;
|
||||
size_t data_moved = 0;
|
||||
|
||||
if (aes == NULL || buf == NULL)
|
||||
return MZ_PARAM_ERROR;
|
||||
if (size != MZ_AES_BLOCK_SIZE)
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
aes->error = CCCryptorUpdate(aes->crypt, buf, size, buf, size, &data_moved);
|
||||
|
||||
if (aes->error != kCCSuccess)
|
||||
return MZ_HASH_ERROR;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int32_t mz_crypt_aes_set_encrypt_key(void *handle, const void *key, int32_t key_length)
|
||||
{
|
||||
mz_crypt_aes *aes = (mz_crypt_aes *)handle;
|
||||
|
||||
|
||||
if (aes == NULL || key == NULL || key_length == 0)
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
mz_crypt_aes_reset(handle);
|
||||
|
||||
aes->error = CCCryptorCreate(kCCEncrypt, kCCAlgorithmAES, kCCOptionECBMode,
|
||||
key, key_length, NULL, &aes->crypt);
|
||||
|
||||
if (aes->error != kCCSuccess)
|
||||
return MZ_HASH_ERROR;
|
||||
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_crypt_aes_set_decrypt_key(void *handle, const void *key, int32_t key_length)
|
||||
{
|
||||
mz_crypt_aes *aes = (mz_crypt_aes *)handle;
|
||||
|
||||
|
||||
if (aes == NULL || key == NULL || key_length == 0)
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
mz_crypt_aes_reset(handle);
|
||||
|
||||
aes->error = CCCryptorCreate(kCCDecrypt, kCCAlgorithmAES, kCCOptionECBMode,
|
||||
key, key_length, NULL, &aes->crypt);
|
||||
|
||||
if (aes->error != kCCSuccess)
|
||||
return MZ_HASH_ERROR;
|
||||
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
void mz_crypt_aes_set_mode(void *handle, int32_t mode)
|
||||
{
|
||||
mz_crypt_aes *aes = (mz_crypt_aes *)handle;
|
||||
aes->mode = mode;
|
||||
}
|
||||
|
||||
void *mz_crypt_aes_create(void **handle)
|
||||
{
|
||||
mz_crypt_aes *aes = NULL;
|
||||
|
||||
aes = (mz_crypt_aes *)MZ_ALLOC(sizeof(mz_crypt_aes));
|
||||
if (aes != NULL)
|
||||
memset(aes, 0, sizeof(mz_crypt_aes));
|
||||
if (handle != NULL)
|
||||
*handle = aes;
|
||||
|
||||
return aes;
|
||||
}
|
||||
|
||||
void mz_crypt_aes_delete(void **handle)
|
||||
{
|
||||
mz_crypt_aes *aes = NULL;
|
||||
if (handle == NULL)
|
||||
return;
|
||||
aes = (mz_crypt_aes *)*handle;
|
||||
if (aes != NULL)
|
||||
{
|
||||
mz_crypt_aes_reset(*handle);
|
||||
MZ_FREE(aes);
|
||||
}
|
||||
*handle = NULL;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
typedef struct mz_crypt_hmac_s {
|
||||
CCHmacContext ctx;
|
||||
int32_t initialized;
|
||||
int32_t error;
|
||||
uint16_t algorithm;
|
||||
} mz_crypt_hmac;
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
static void mz_crypt_hmac_free(void *handle)
|
||||
{
|
||||
mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle;
|
||||
memset(&hmac->ctx, 0, sizeof(hmac->ctx));
|
||||
}
|
||||
|
||||
void mz_crypt_hmac_reset(void *handle)
|
||||
{
|
||||
mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle;
|
||||
mz_crypt_hmac_free(handle);
|
||||
hmac->error = 0;
|
||||
}
|
||||
|
||||
int32_t mz_crypt_hmac_init(void *handle, const void *key, int32_t key_length)
|
||||
{
|
||||
mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle;
|
||||
CCHmacAlgorithm algorithm = 0;
|
||||
|
||||
if (hmac == NULL || key == NULL)
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
mz_crypt_hmac_reset(handle);
|
||||
|
||||
if (hmac->algorithm == MZ_HASH_SHA1)
|
||||
algorithm = kCCHmacAlgSHA1;
|
||||
else if (hmac->algorithm == MZ_HASH_SHA256)
|
||||
algorithm = kCCHmacAlgSHA256;
|
||||
else
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
CCHmacInit(&hmac->ctx, algorithm, key, key_length);
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_crypt_hmac_update(void *handle, const void *buf, int32_t size)
|
||||
{
|
||||
mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle;
|
||||
|
||||
if (hmac == NULL || buf == NULL)
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
CCHmacUpdate(&hmac->ctx, buf, size);
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_crypt_hmac_end(void *handle, uint8_t *digest, int32_t digest_size)
|
||||
{
|
||||
mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle;
|
||||
|
||||
if (hmac == NULL || digest == NULL)
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
if (hmac->algorithm == MZ_HASH_SHA1)
|
||||
{
|
||||
if (digest_size < MZ_HASH_SHA1_SIZE)
|
||||
return MZ_BUF_ERROR;
|
||||
CCHmacFinal(&hmac->ctx, digest);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (digest_size < MZ_HASH_SHA256_SIZE)
|
||||
return MZ_BUF_ERROR;
|
||||
CCHmacFinal(&hmac->ctx, digest);
|
||||
}
|
||||
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
void mz_crypt_hmac_set_algorithm(void *handle, uint16_t algorithm)
|
||||
{
|
||||
mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle;
|
||||
hmac->algorithm = algorithm;
|
||||
}
|
||||
|
||||
int32_t mz_crypt_hmac_copy(void *src_handle, void *target_handle)
|
||||
{
|
||||
mz_crypt_hmac *source = (mz_crypt_hmac *)src_handle;
|
||||
mz_crypt_hmac *target = (mz_crypt_hmac *)target_handle;
|
||||
|
||||
if (source == NULL || target == NULL)
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
memcpy(&target->ctx, &source->ctx, sizeof(CCHmacContext));
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
void *mz_crypt_hmac_create(void **handle)
|
||||
{
|
||||
mz_crypt_hmac *hmac = NULL;
|
||||
|
||||
hmac = (mz_crypt_hmac *)MZ_ALLOC(sizeof(mz_crypt_hmac));
|
||||
if (hmac != NULL)
|
||||
{
|
||||
memset(hmac, 0, sizeof(mz_crypt_hmac));
|
||||
hmac->algorithm = MZ_HASH_SHA256;
|
||||
}
|
||||
if (handle != NULL)
|
||||
*handle = hmac;
|
||||
|
||||
return hmac;
|
||||
}
|
||||
|
||||
void mz_crypt_hmac_delete(void **handle)
|
||||
{
|
||||
mz_crypt_hmac *hmac = NULL;
|
||||
if (handle == NULL)
|
||||
return;
|
||||
hmac = (mz_crypt_hmac *)*handle;
|
||||
if (hmac != NULL)
|
||||
{
|
||||
mz_crypt_hmac_free(*handle);
|
||||
MZ_FREE(hmac);
|
||||
}
|
||||
*handle = NULL;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#if defined(MZ_ZIP_SIGNING)
|
||||
int32_t mz_crypt_sign(uint8_t *message, int32_t message_size, uint8_t *cert_data, int32_t cert_data_size,
|
||||
const char *cert_pwd, uint8_t **signature, int32_t *signature_size)
|
||||
{
|
||||
CFStringRef password_ref = NULL;
|
||||
CFDictionaryRef options_dict = NULL;
|
||||
CFDictionaryRef identity_trust = NULL;
|
||||
CFDataRef signature_out = NULL;
|
||||
CFDataRef pkcs12_data = NULL;
|
||||
CFArrayRef items = 0;
|
||||
SecIdentityRef identity = NULL;
|
||||
SecTrustRef trust = NULL;
|
||||
OSStatus status = noErr;
|
||||
const void *options_key[2] = { kSecImportExportPassphrase, kSecReturnRef };
|
||||
const void *options_values[2] = { 0, kCFBooleanTrue };
|
||||
int32_t err = MZ_SIGN_ERROR;
|
||||
|
||||
|
||||
if (message == NULL || cert_data == NULL || signature == NULL || signature_size == NULL)
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
*signature = NULL;
|
||||
*signature_size = 0;
|
||||
|
||||
password_ref = CFStringCreateWithCString(0, cert_pwd, kCFStringEncodingUTF8);
|
||||
options_values[0] = password_ref;
|
||||
|
||||
options_dict = CFDictionaryCreate(0, options_key, options_values, 2, 0, 0);
|
||||
if (options_dict)
|
||||
pkcs12_data = CFDataCreate(0, cert_data, cert_data_size);
|
||||
if (pkcs12_data)
|
||||
status = SecPKCS12Import(pkcs12_data, options_dict, &items);
|
||||
if (status == noErr)
|
||||
identity_trust = CFArrayGetValueAtIndex(items, 0);
|
||||
if (identity_trust)
|
||||
identity = (SecIdentityRef)CFDictionaryGetValue(identity_trust, kSecImportItemIdentity);
|
||||
if (identity)
|
||||
trust = (SecTrustRef)CFDictionaryGetValue(identity_trust, kSecImportItemTrust);
|
||||
if (trust)
|
||||
{
|
||||
status = CMSEncodeContent(identity, NULL, NULL, FALSE, 0, message, message_size, &signature_out);
|
||||
|
||||
if (status == errSecSuccess)
|
||||
{
|
||||
*signature_size = CFDataGetLength(signature_out);
|
||||
*signature = (uint8_t *)MZ_ALLOC(*signature_size);
|
||||
|
||||
memcpy(*signature, CFDataGetBytePtr(signature_out), *signature_size);
|
||||
|
||||
err = MZ_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (signature_out)
|
||||
CFRelease(signature_out);
|
||||
if (items)
|
||||
CFRelease(items);
|
||||
if (pkcs12_data)
|
||||
CFRelease(pkcs12_data);
|
||||
if (options_dict)
|
||||
CFRelease(options_dict);
|
||||
if (password_ref)
|
||||
CFRelease(password_ref);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int32_t mz_crypt_sign_verify(uint8_t *message, int32_t message_size, uint8_t *signature, int32_t signature_size)
|
||||
{
|
||||
CMSDecoderRef decoder = NULL;
|
||||
CMSSignerStatus signer_status = 0;
|
||||
CFDataRef message_out = NULL;
|
||||
SecPolicyRef trust_policy = NULL;
|
||||
OSStatus status = noErr;
|
||||
OSStatus verify_status = noErr;
|
||||
size_t signer_count = 0;
|
||||
size_t i = 0;
|
||||
int32_t err = MZ_SIGN_ERROR;
|
||||
|
||||
if (message == NULL || signature == NULL)
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
status = CMSDecoderCreate(&decoder);
|
||||
if (status == errSecSuccess)
|
||||
status = CMSDecoderUpdateMessage(decoder, signature, signature_size);
|
||||
if (status == errSecSuccess)
|
||||
status = CMSDecoderFinalizeMessage(decoder);
|
||||
if (status == errSecSuccess)
|
||||
trust_policy = SecPolicyCreateBasicX509();
|
||||
|
||||
if (status == errSecSuccess && trust_policy)
|
||||
{
|
||||
CMSDecoderGetNumSigners(decoder, &signer_count);
|
||||
if (signer_count > 0)
|
||||
err = MZ_OK;
|
||||
for (i = 0; i < signer_count; i += 1)
|
||||
{
|
||||
status = CMSDecoderCopySignerStatus(decoder, i, trust_policy, TRUE, &signer_status, NULL, &verify_status);
|
||||
if (status != errSecSuccess || verify_status != 0 || signer_status != kCMSSignerValid)
|
||||
{
|
||||
err = MZ_SIGN_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (err == MZ_OK)
|
||||
{
|
||||
status = CMSDecoderCopyContent(decoder, &message_out);
|
||||
if ((status != errSecSuccess) ||
|
||||
(CFDataGetLength(message_out) != message_size) ||
|
||||
(memcmp(message, CFDataGetBytePtr(message_out), message_size) != 0))
|
||||
err = MZ_SIGN_ERROR;
|
||||
}
|
||||
|
||||
if (trust_policy)
|
||||
CFRelease(trust_policy);
|
||||
if (decoder)
|
||||
CFRelease(decoder);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif
|
401
third-party/ZipArchive/Sources/minizip/mz_os.c
vendored
Normal file
401
third-party/ZipArchive/Sources/minizip/mz_os.c
vendored
Normal file
@ -0,0 +1,401 @@
|
||||
/* mz_os.c -- System functions
|
||||
Version 2.9.2, February 12, 2020
|
||||
part of the MiniZip project
|
||||
|
||||
Copyright (C) 2010-2020 Nathan Moinvaziri
|
||||
https://github.com/nmoinvaz/minizip
|
||||
Copyright (C) 1998-2010 Gilles Vollant
|
||||
https://www.winimage.com/zLibDll/minizip.html
|
||||
|
||||
This program is distributed under the terms of the same license as zlib.
|
||||
See the accompanying LICENSE file for the full text of the license.
|
||||
*/
|
||||
|
||||
#include "mz.h"
|
||||
#include "mz_crypt.h"
|
||||
#include "mz_os.h"
|
||||
#include "mz_strm.h"
|
||||
#include "mz_strm_os.h"
|
||||
|
||||
#include <ctype.h> /* tolower */
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_path_combine(char *path, const char *join, int32_t max_path)
|
||||
{
|
||||
int32_t path_len = 0;
|
||||
|
||||
if (path == NULL || join == NULL || max_path == 0)
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
path_len = (int32_t)strlen(path);
|
||||
|
||||
if (path_len == 0)
|
||||
{
|
||||
strncpy(path, join, max_path - 1);
|
||||
path[max_path - 1] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
mz_path_append_slash(path, max_path, MZ_PATH_SLASH_PLATFORM);
|
||||
strncat(path, join, max_path - path_len);
|
||||
}
|
||||
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_path_append_slash(char *path, int32_t max_path, char slash)
|
||||
{
|
||||
int32_t path_len = (int32_t)strlen(path);
|
||||
if ((path_len + 2) >= max_path)
|
||||
return MZ_BUF_ERROR;
|
||||
if (path[path_len - 1] != '\\' && path[path_len - 1] != '/')
|
||||
{
|
||||
path[path_len] = slash;
|
||||
path[path_len + 1] = 0;
|
||||
}
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_path_remove_slash(char *path)
|
||||
{
|
||||
int32_t path_len = (int32_t)strlen(path);
|
||||
while (path_len > 0)
|
||||
{
|
||||
if (path[path_len - 1] == '\\' || path[path_len - 1] == '/')
|
||||
path[path_len - 1] = 0;
|
||||
else
|
||||
break;
|
||||
|
||||
path_len -= 1;
|
||||
}
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_path_has_slash(const char *path)
|
||||
{
|
||||
int32_t path_len = (int32_t)strlen(path);
|
||||
if (path[path_len - 1] != '\\' && path[path_len - 1] != '/')
|
||||
return MZ_EXIST_ERROR;
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_path_convert_slashes(char *path, char slash)
|
||||
{
|
||||
int32_t i = 0;
|
||||
|
||||
for (i = 0; i < (int32_t)strlen(path); i += 1)
|
||||
{
|
||||
if (path[i] == '\\' || path[i] == '/')
|
||||
path[i] = slash;
|
||||
}
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_path_compare_wc(const char *path, const char *wildcard, uint8_t ignore_case)
|
||||
{
|
||||
while (*path != 0)
|
||||
{
|
||||
switch (*wildcard)
|
||||
{
|
||||
case '*':
|
||||
|
||||
if (*(wildcard + 1) == 0)
|
||||
return MZ_OK;
|
||||
|
||||
while (*path != 0)
|
||||
{
|
||||
if (mz_path_compare_wc(path, (wildcard + 1), ignore_case) == MZ_OK)
|
||||
return MZ_OK;
|
||||
|
||||
path += 1;
|
||||
}
|
||||
|
||||
return MZ_EXIST_ERROR;
|
||||
|
||||
default:
|
||||
/* Ignore differences in path slashes on platforms */
|
||||
if ((*path == '\\' && *wildcard == '/') || (*path == '/' && *wildcard == '\\'))
|
||||
break;
|
||||
|
||||
if (ignore_case)
|
||||
{
|
||||
if (tolower(*path) != tolower(*wildcard))
|
||||
return MZ_EXIST_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*path != *wildcard)
|
||||
return MZ_EXIST_ERROR;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
path += 1;
|
||||
wildcard += 1;
|
||||
}
|
||||
|
||||
if ((*wildcard != 0) && (*wildcard != '*'))
|
||||
return MZ_EXIST_ERROR;
|
||||
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_path_resolve(const char *path, char *output, int32_t max_output)
|
||||
{
|
||||
const char *source = path;
|
||||
const char *check = output;
|
||||
char *target = output;
|
||||
|
||||
|
||||
if (max_output <= 0)
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
while (*source != 0 && max_output > 1)
|
||||
{
|
||||
check = source;
|
||||
if ((*check == '\\') || (*check == '/'))
|
||||
check += 1;
|
||||
|
||||
if ((source == path) || (target == output) || (check != source))
|
||||
{
|
||||
/* Skip double paths */
|
||||
if ((*check == '\\') || (*check == '/'))
|
||||
{
|
||||
source += 1;
|
||||
continue;
|
||||
}
|
||||
if ((*check != 0) && (*check == '.'))
|
||||
{
|
||||
check += 1;
|
||||
|
||||
/* Remove . if at end of string and not at the beginning */
|
||||
if ((*check == 0) && (source != path && target != output))
|
||||
{
|
||||
/* Copy last slash */
|
||||
*target = *source;
|
||||
target += 1;
|
||||
max_output -= 1;
|
||||
source += (check - source);
|
||||
continue;
|
||||
}
|
||||
/* Remove . if not at end of string */
|
||||
else if ((*check == '\\') || (*check == '/'))
|
||||
{
|
||||
source += (check - source);
|
||||
/* Skip slash if at beginning of string */
|
||||
if (target == output && *source != 0)
|
||||
source += 1;
|
||||
continue;
|
||||
}
|
||||
/* Go to parent directory .. */
|
||||
else if (*check == '.')
|
||||
{
|
||||
check += 1;
|
||||
if ((*check == 0) || (*check == '\\' || *check == '/'))
|
||||
{
|
||||
source += (check - source);
|
||||
|
||||
/* Search backwards for previous slash */
|
||||
if (target != output)
|
||||
{
|
||||
target -= 1;
|
||||
do
|
||||
{
|
||||
if ((*target == '\\') || (*target == '/'))
|
||||
break;
|
||||
|
||||
target -= 1;
|
||||
max_output += 1;
|
||||
}
|
||||
while (target > output);
|
||||
}
|
||||
|
||||
if ((target == output) && (*source != 0))
|
||||
source += 1;
|
||||
if ((*target == '\\' || *target == '/') && (*source == 0))
|
||||
target += 1;
|
||||
|
||||
*target = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*target = *source;
|
||||
|
||||
source += 1;
|
||||
target += 1;
|
||||
max_output -= 1;
|
||||
}
|
||||
|
||||
*target = 0;
|
||||
|
||||
if (*path == 0)
|
||||
return MZ_INTERNAL_ERROR;
|
||||
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_path_remove_filename(char *path)
|
||||
{
|
||||
char *path_ptr = NULL;
|
||||
|
||||
if (path == NULL)
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
path_ptr = path + strlen(path) - 1;
|
||||
|
||||
while (path_ptr > path)
|
||||
{
|
||||
if ((*path_ptr == '/') || (*path_ptr == '\\'))
|
||||
{
|
||||
*path_ptr = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
path_ptr -= 1;
|
||||
}
|
||||
|
||||
if (path_ptr == path)
|
||||
*path_ptr = 0;
|
||||
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_path_remove_extension(char *path)
|
||||
{
|
||||
char *path_ptr = NULL;
|
||||
|
||||
if (path == NULL)
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
path_ptr = path + strlen(path) - 1;
|
||||
|
||||
while (path_ptr > path)
|
||||
{
|
||||
if ((*path_ptr == '/') || (*path_ptr == '\\'))
|
||||
break;
|
||||
if (*path_ptr == '.')
|
||||
{
|
||||
*path_ptr = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
path_ptr -= 1;
|
||||
}
|
||||
|
||||
if (path_ptr == path)
|
||||
*path_ptr = 0;
|
||||
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_path_get_filename(const char *path, const char **filename)
|
||||
{
|
||||
const char *match = NULL;
|
||||
|
||||
if (path == NULL || filename == NULL)
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
*filename = NULL;
|
||||
|
||||
for (match = path; *match != 0; match += 1)
|
||||
{
|
||||
if ((*match == '\\') || (*match == '/'))
|
||||
*filename = match + 1;
|
||||
}
|
||||
|
||||
if (*filename == NULL)
|
||||
return MZ_EXIST_ERROR;
|
||||
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_dir_make(const char *path)
|
||||
{
|
||||
int32_t err = MZ_OK;
|
||||
int16_t len = 0;
|
||||
char *current_dir = NULL;
|
||||
char *match = NULL;
|
||||
char hold = 0;
|
||||
|
||||
|
||||
len = (int16_t)strlen(path);
|
||||
if (len <= 0)
|
||||
return 0;
|
||||
|
||||
current_dir = (char *)MZ_ALLOC((uint16_t)len + 1);
|
||||
if (current_dir == NULL)
|
||||
return MZ_MEM_ERROR;
|
||||
|
||||
strcpy(current_dir, path);
|
||||
mz_path_remove_slash(current_dir);
|
||||
|
||||
err = mz_os_make_dir(current_dir);
|
||||
if (err != MZ_OK)
|
||||
{
|
||||
match = current_dir + 1;
|
||||
while (1)
|
||||
{
|
||||
while (*match != 0 && *match != '\\' && *match != '/')
|
||||
match += 1;
|
||||
hold = *match;
|
||||
*match = 0;
|
||||
|
||||
err = mz_os_make_dir(current_dir);
|
||||
if (err != MZ_OK)
|
||||
break;
|
||||
if (hold == 0)
|
||||
break;
|
||||
|
||||
*match = hold;
|
||||
match += 1;
|
||||
}
|
||||
}
|
||||
|
||||
MZ_FREE(current_dir);
|
||||
return err;
|
||||
}
|
||||
|
||||
int32_t mz_file_get_crc(const char *path, uint32_t *result_crc)
|
||||
{
|
||||
void *stream = NULL;
|
||||
uint32_t crc32 = 0;
|
||||
int32_t read = 0;
|
||||
int32_t err = MZ_OK;
|
||||
uint8_t buf[16384];
|
||||
|
||||
mz_stream_os_create(&stream);
|
||||
|
||||
err = mz_stream_os_open(stream, path, MZ_OPEN_MODE_READ);
|
||||
|
||||
if (err == MZ_OK)
|
||||
{
|
||||
do
|
||||
{
|
||||
read = mz_stream_os_read(stream, buf, sizeof(buf));
|
||||
|
||||
if (read < 0)
|
||||
{
|
||||
err = read;
|
||||
break;
|
||||
}
|
||||
|
||||
crc32 = mz_crypt_crc32_update(crc32, buf, read);
|
||||
}
|
||||
while ((err == MZ_OK) && (read > 0));
|
||||
|
||||
mz_stream_os_close(stream);
|
||||
}
|
||||
|
||||
*result_crc = crc32;
|
||||
|
||||
mz_stream_os_delete(&stream);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
176
third-party/ZipArchive/Sources/minizip/mz_os.h
vendored
Normal file
176
third-party/ZipArchive/Sources/minizip/mz_os.h
vendored
Normal file
@ -0,0 +1,176 @@
|
||||
/* mz_os.h -- System functions
|
||||
Version 2.9.2, February 12, 2020
|
||||
part of the MiniZip project
|
||||
|
||||
Copyright (C) 2010-2020 Nathan Moinvaziri
|
||||
https://github.com/nmoinvaz/minizip
|
||||
|
||||
This program is distributed under the terms of the same license as zlib.
|
||||
See the accompanying LICENSE file for the full text of the license.
|
||||
*/
|
||||
|
||||
#ifndef MZ_OS_H
|
||||
#define MZ_OS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#if defined(__APPLE__)
|
||||
# define MZ_VERSION_MADEBY_HOST_SYSTEM (MZ_HOST_SYSTEM_OSX_DARWIN)
|
||||
#elif defined(__riscos__)
|
||||
# define MZ_VERSION_MADEBY_HOST_SYSTEM (MZ_HOST_SYSTEM_RISCOS)
|
||||
#elif defined(__unix__)
|
||||
# define MZ_VERSION_MADEBY_HOST_SYSTEM (MZ_HOST_SYSTEM_UNIX)
|
||||
#elif defined(_WIN32)
|
||||
# define MZ_VERSION_MADEBY_HOST_SYSTEM (MZ_HOST_SYSTEM_WINDOWS_NTFS)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_LZMA)
|
||||
# define MZ_VERSION_MADEBY_ZIP_VERSION (63)
|
||||
#elif defined(HAVE_WZAES)
|
||||
# define MZ_VERSION_MADEBY_ZIP_VERSION (51)
|
||||
#elif defined(HAVE_BZIP2)
|
||||
# define MZ_VERSION_MADEBY_ZIP_VERSION (46)
|
||||
#else
|
||||
# define MZ_VERSION_MADEBY_ZIP_VERSION (45)
|
||||
#endif
|
||||
|
||||
#define MZ_VERSION_MADEBY ((MZ_VERSION_MADEBY_HOST_SYSTEM << 8) | \
|
||||
(MZ_VERSION_MADEBY_ZIP_VERSION))
|
||||
|
||||
#define MZ_PATH_SLASH_UNIX ('/')
|
||||
#if defined(_WIN32)
|
||||
# define MZ_PATH_SLASH_PLATFORM ('\\')
|
||||
#else
|
||||
# define MZ_PATH_SLASH_PLATFORM (MZ_PATH_SLASH_UNIX)
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#if defined(_WIN32)
|
||||
struct dirent {
|
||||
char d_name[256];
|
||||
};
|
||||
typedef void* DIR;
|
||||
#else
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
/* Shared functions */
|
||||
|
||||
int32_t mz_path_combine(char *path, const char *join, int32_t max_path);
|
||||
/* Combines two paths */
|
||||
|
||||
int32_t mz_path_append_slash(char *path, int32_t max_path, char slash);
|
||||
/* Appends a path slash on to the end of the path */
|
||||
|
||||
int32_t mz_path_remove_slash(char *path);
|
||||
/* Removes a path slash from the end of the path */
|
||||
|
||||
int32_t mz_path_has_slash(const char *path);
|
||||
/* Returns whether or not the path ends with slash */
|
||||
|
||||
int32_t mz_path_convert_slashes(char *path, char slash);
|
||||
/* Converts the slashes in a path */
|
||||
|
||||
int32_t mz_path_compare_wc(const char *path, const char *wildcard, uint8_t ignore_case);
|
||||
/* Compare two paths with wildcard */
|
||||
|
||||
int32_t mz_path_resolve(const char *path, char *target, int32_t max_target);
|
||||
/* Resolves path */
|
||||
|
||||
int32_t mz_path_remove_filename(char *path);
|
||||
/* Remove the filename from a path */
|
||||
|
||||
int32_t mz_path_remove_extension(char *path);
|
||||
/* Remove the extension from a path */
|
||||
|
||||
int32_t mz_path_get_filename(const char *path, const char **filename);
|
||||
/* Get the filename from a path */
|
||||
|
||||
int32_t mz_dir_make(const char *path);
|
||||
/* Creates a directory recursively */
|
||||
|
||||
int32_t mz_file_get_crc(const char *path, uint32_t *result_crc);
|
||||
/* Gets the crc32 hash of a file */
|
||||
|
||||
/***************************************************************************/
|
||||
/* Platform specific functions */
|
||||
|
||||
wchar_t *mz_os_unicode_string_create(const char *string, int32_t encoding);
|
||||
/* Create unicode string from a utf8 string */
|
||||
|
||||
void mz_os_unicode_string_delete(wchar_t **string);
|
||||
/* Delete a unicode string that was created */
|
||||
|
||||
uint8_t *mz_os_utf8_string_create(const char *string, int32_t encoding);
|
||||
/* Create a utf8 string from a string with another encoding */
|
||||
|
||||
void mz_os_utf8_string_delete(uint8_t **string);
|
||||
/* Delete a utf8 string that was created */
|
||||
|
||||
int32_t mz_os_rand(uint8_t *buf, int32_t size);
|
||||
/* Random number generator (not cryptographically secure) */
|
||||
|
||||
int32_t mz_os_rename(const char *source_path, const char *target_path);
|
||||
/* Rename a file */
|
||||
|
||||
int32_t mz_os_unlink(const char *path);
|
||||
/* Delete an existing file */
|
||||
|
||||
int32_t mz_os_file_exists(const char *path);
|
||||
/* Check to see if a file exists */
|
||||
|
||||
int64_t mz_os_get_file_size(const char *path);
|
||||
/* Gets the length of a file */
|
||||
|
||||
int32_t mz_os_get_file_date(const char *path, time_t *modified_date, time_t *accessed_date, time_t *creation_date);
|
||||
/* Gets a file's modified, access, and creation dates if supported */
|
||||
|
||||
int32_t mz_os_set_file_date(const char *path, time_t modified_date, time_t accessed_date, time_t creation_date);
|
||||
/* Sets a file's modified, access, and creation dates if supported */
|
||||
|
||||
int32_t mz_os_get_file_attribs(const char *path, uint32_t *attributes);
|
||||
/* Gets a file's attributes */
|
||||
|
||||
int32_t mz_os_set_file_attribs(const char *path, uint32_t attributes);
|
||||
/* Sets a file's attributes */
|
||||
|
||||
int32_t mz_os_make_dir(const char *path);
|
||||
/* Recursively creates a directory */
|
||||
|
||||
DIR* mz_os_open_dir(const char *path);
|
||||
/* Opens a directory for listing */
|
||||
struct
|
||||
dirent* mz_os_read_dir(DIR *dir);
|
||||
/* Reads a directory listing entry */
|
||||
|
||||
int32_t mz_os_close_dir(DIR *dir);
|
||||
/* Closes a directory that has been opened for listing */
|
||||
|
||||
int32_t mz_os_is_dir(const char *path);
|
||||
/* Checks to see if path is a directory */
|
||||
|
||||
int32_t mz_os_is_symlink(const char *path);
|
||||
/* Checks to see if path is a symbolic link */
|
||||
|
||||
int32_t mz_os_make_symlink(const char *path, const char *target_path);
|
||||
/* Creates a symbolic link pointing to a target */
|
||||
|
||||
int32_t mz_os_read_symlink(const char *path, char *target_path, int32_t max_target_path);
|
||||
/* Gets the target path for a symbolic link */
|
||||
|
||||
uint64_t mz_os_ms_time(void);
|
||||
/* Gets the time in milliseconds */
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
329
third-party/ZipArchive/Sources/minizip/mz_os_posix.c
vendored
Normal file
329
third-party/ZipArchive/Sources/minizip/mz_os_posix.c
vendored
Normal file
@ -0,0 +1,329 @@
|
||||
/* mz_os_posix.c -- System functions for posix
|
||||
Version 2.9.2, February 12, 2020
|
||||
part of the MiniZip project
|
||||
|
||||
Copyright (C) 2010-2020 Nathan Moinvaziri
|
||||
https://github.com/nmoinvaz/minizip
|
||||
|
||||
This program is distributed under the terms of the same license as zlib.
|
||||
See the accompanying LICENSE file for the full text of the license.
|
||||
*/
|
||||
|
||||
#include "mz.h"
|
||||
#include "mz_strm.h"
|
||||
#include "mz_os.h"
|
||||
|
||||
#include <stdio.h> /* rename */
|
||||
#include <errno.h>
|
||||
#include <iconv.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if defined(__APPLE__) || defined(__unix__) || defined(__riscos__)
|
||||
# include <utime.h>
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#if defined(__APPLE__)
|
||||
# include <mach/clock.h>
|
||||
# include <mach/mach.h>
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
uint8_t *mz_os_utf8_string_create(const char *string, int32_t encoding)
|
||||
{
|
||||
iconv_t cd;
|
||||
const char *from_encoding = NULL;
|
||||
size_t result = 0;
|
||||
size_t string_length = 0;
|
||||
size_t string_utf8_size = 0;
|
||||
uint8_t *string_utf8 = NULL;
|
||||
uint8_t *string_utf8_ptr = NULL;
|
||||
|
||||
if (string == NULL)
|
||||
return NULL;
|
||||
|
||||
if (encoding == MZ_ENCODING_CODEPAGE_437)
|
||||
from_encoding = "CP437";
|
||||
else if (encoding == MZ_ENCODING_CODEPAGE_932)
|
||||
from_encoding = "CP932";
|
||||
else if (encoding == MZ_ENCODING_CODEPAGE_936)
|
||||
from_encoding = "CP936";
|
||||
else if (encoding == MZ_ENCODING_CODEPAGE_950)
|
||||
from_encoding = "CP950";
|
||||
else if (encoding == MZ_ENCODING_UTF8)
|
||||
from_encoding = "UTF-8";
|
||||
else
|
||||
return NULL;
|
||||
|
||||
cd = iconv_open("UTF-8", from_encoding);
|
||||
if (cd == (iconv_t)-1)
|
||||
return NULL;
|
||||
|
||||
string_length = strlen(string);
|
||||
string_utf8_size = string_length * 2;
|
||||
string_utf8 = (uint8_t *)MZ_ALLOC((int32_t)(string_utf8_size + 1));
|
||||
string_utf8_ptr = string_utf8;
|
||||
|
||||
if (string_utf8)
|
||||
{
|
||||
memset(string_utf8, 0, string_utf8_size + 1);
|
||||
|
||||
result = iconv(cd, (char **)&string, &string_length,
|
||||
(char **)&string_utf8_ptr, &string_utf8_size);
|
||||
}
|
||||
|
||||
iconv_close(cd);
|
||||
|
||||
if (result == (size_t)-1)
|
||||
{
|
||||
MZ_FREE(string_utf8);
|
||||
string_utf8 = NULL;
|
||||
}
|
||||
|
||||
return string_utf8;
|
||||
}
|
||||
|
||||
void mz_os_utf8_string_delete(uint8_t **string)
|
||||
{
|
||||
if (string != NULL)
|
||||
{
|
||||
MZ_FREE(*string);
|
||||
*string = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_os_rand(uint8_t *buf, int32_t size)
|
||||
{
|
||||
static unsigned calls = 0;
|
||||
int32_t i = 0;
|
||||
|
||||
/* Ensure different random header each time */
|
||||
if (++calls == 1)
|
||||
{
|
||||
#define PI_SEED 3141592654UL
|
||||
srand((unsigned)(time(NULL) ^ PI_SEED));
|
||||
}
|
||||
|
||||
while (i < size)
|
||||
buf[i++] = (rand() >> 7) & 0xff;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int32_t mz_os_rename(const char *source_path, const char *target_path)
|
||||
{
|
||||
if (rename(source_path, target_path) == -1)
|
||||
return MZ_EXIST_ERROR;
|
||||
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_os_unlink(const char *path)
|
||||
{
|
||||
if (unlink(path) == -1)
|
||||
return MZ_EXIST_ERROR;
|
||||
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_os_file_exists(const char *path)
|
||||
{
|
||||
struct stat path_stat;
|
||||
|
||||
memset(&path_stat, 0, sizeof(path_stat));
|
||||
if (stat(path, &path_stat) == 0)
|
||||
return MZ_OK;
|
||||
return MZ_EXIST_ERROR;
|
||||
}
|
||||
|
||||
int64_t mz_os_get_file_size(const char *path)
|
||||
{
|
||||
struct stat path_stat;
|
||||
|
||||
memset(&path_stat, 0, sizeof(path_stat));
|
||||
if (stat(path, &path_stat) == 0)
|
||||
{
|
||||
/* Stat returns size taken up by directory entry, so return 0 */
|
||||
if (S_ISDIR(path_stat.st_mode))
|
||||
return 0;
|
||||
|
||||
return path_stat.st_size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t mz_os_get_file_date(const char *path, time_t *modified_date, time_t *accessed_date, time_t *creation_date)
|
||||
{
|
||||
struct stat path_stat;
|
||||
char *name = NULL;
|
||||
size_t len = 0;
|
||||
int32_t err = MZ_INTERNAL_ERROR;
|
||||
|
||||
memset(&path_stat, 0, sizeof(path_stat));
|
||||
|
||||
if (strcmp(path, "-") != 0)
|
||||
{
|
||||
/* Not all systems allow stat'ing a file with / appended */
|
||||
len = strlen(path);
|
||||
name = (char *)malloc(len + 1);
|
||||
strncpy(name, path, len + 1);
|
||||
mz_path_remove_slash(name);
|
||||
|
||||
if (stat(name, &path_stat) == 0)
|
||||
{
|
||||
if (modified_date != NULL)
|
||||
*modified_date = path_stat.st_mtime;
|
||||
if (accessed_date != NULL)
|
||||
*accessed_date = path_stat.st_atime;
|
||||
/* Creation date not supported */
|
||||
if (creation_date != NULL)
|
||||
*creation_date = 0;
|
||||
|
||||
err = MZ_OK;
|
||||
}
|
||||
|
||||
free(name);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int32_t mz_os_set_file_date(const char *path, time_t modified_date, time_t accessed_date, time_t creation_date)
|
||||
{
|
||||
struct utimbuf ut;
|
||||
|
||||
ut.actime = accessed_date;
|
||||
ut.modtime = modified_date;
|
||||
|
||||
/* Creation date not supported */
|
||||
MZ_UNUSED(creation_date);
|
||||
|
||||
if (utime(path, &ut) != 0)
|
||||
return MZ_INTERNAL_ERROR;
|
||||
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_os_get_file_attribs(const char *path, uint32_t *attributes)
|
||||
{
|
||||
struct stat path_stat;
|
||||
int32_t err = MZ_OK;
|
||||
|
||||
memset(&path_stat, 0, sizeof(path_stat));
|
||||
if (lstat(path, &path_stat) == -1)
|
||||
err = MZ_INTERNAL_ERROR;
|
||||
*attributes = path_stat.st_mode;
|
||||
return err;
|
||||
}
|
||||
|
||||
int32_t mz_os_set_file_attribs(const char *path, uint32_t attributes)
|
||||
{
|
||||
int32_t err = MZ_OK;
|
||||
|
||||
if (chmod(path, (mode_t)attributes) == -1)
|
||||
err = MZ_INTERNAL_ERROR;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int32_t mz_os_make_dir(const char *path)
|
||||
{
|
||||
int32_t err = 0;
|
||||
|
||||
err = mkdir(path, 0755);
|
||||
|
||||
if (err != 0 && errno != EEXIST)
|
||||
return MZ_INTERNAL_ERROR;
|
||||
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
DIR* mz_os_open_dir(const char *path)
|
||||
{
|
||||
return opendir(path);
|
||||
}
|
||||
|
||||
struct dirent* mz_os_read_dir(DIR *dir)
|
||||
{
|
||||
if (dir == NULL)
|
||||
return NULL;
|
||||
return readdir(dir);
|
||||
}
|
||||
|
||||
int32_t mz_os_close_dir(DIR *dir)
|
||||
{
|
||||
if (dir == NULL)
|
||||
return MZ_PARAM_ERROR;
|
||||
if (closedir(dir) == -1)
|
||||
return MZ_INTERNAL_ERROR;
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_os_is_dir(const char *path)
|
||||
{
|
||||
struct stat path_stat;
|
||||
|
||||
memset(&path_stat, 0, sizeof(path_stat));
|
||||
stat(path, &path_stat);
|
||||
if (S_ISDIR(path_stat.st_mode))
|
||||
return MZ_OK;
|
||||
|
||||
return MZ_EXIST_ERROR;
|
||||
}
|
||||
|
||||
int32_t mz_os_is_symlink(const char *path)
|
||||
{
|
||||
struct stat path_stat;
|
||||
|
||||
memset(&path_stat, 0, sizeof(path_stat));
|
||||
lstat(path, &path_stat);
|
||||
if (S_ISLNK(path_stat.st_mode))
|
||||
return MZ_OK;
|
||||
|
||||
return MZ_EXIST_ERROR;
|
||||
}
|
||||
|
||||
int32_t mz_os_make_symlink(const char *path, const char *target_path)
|
||||
{
|
||||
if (symlink(target_path, path) != 0)
|
||||
return MZ_INTERNAL_ERROR;
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_os_read_symlink(const char *path, char *target_path, int32_t max_target_path)
|
||||
{
|
||||
size_t length = 0;
|
||||
|
||||
length = (size_t)readlink(path, target_path, max_target_path - 1);
|
||||
if (length == (size_t)-1)
|
||||
return MZ_EXIST_ERROR;
|
||||
|
||||
target_path[length] = 0;
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
uint64_t mz_os_ms_time(void)
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
#if defined(__APPLE__)
|
||||
clock_serv_t cclock;
|
||||
mach_timespec_t mts;
|
||||
|
||||
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
|
||||
clock_get_time(cclock, &mts);
|
||||
mach_port_deallocate(mach_task_self(), cclock);
|
||||
|
||||
ts.tv_sec = mts.tv_sec;
|
||||
ts.tv_nsec = mts.tv_nsec;
|
||||
#else
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
#endif
|
||||
|
||||
return ((uint64_t)ts.tv_sec * 1000) + ((uint64_t)ts.tv_nsec / 1000000);
|
||||
}
|
623
third-party/ZipArchive/Sources/minizip/mz_strm.c
vendored
Normal file
623
third-party/ZipArchive/Sources/minizip/mz_strm.c
vendored
Normal file
@ -0,0 +1,623 @@
|
||||
/* mz_strm.c -- Stream interface
|
||||
Version 2.9.2, February 12, 2020
|
||||
part of the MiniZip project
|
||||
|
||||
Copyright (C) 2010-2020 Nathan Moinvaziri
|
||||
https://github.com/nmoinvaz/minizip
|
||||
|
||||
This program is distributed under the terms of the same license as zlib.
|
||||
See the accompanying LICENSE file for the full text of the license.
|
||||
*/
|
||||
|
||||
#include "mz.h"
|
||||
#include "mz_strm.h"
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#define MZ_STREAM_FIND_SIZE (1024)
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_stream_open(void *stream, const char *path, int32_t mode)
|
||||
{
|
||||
mz_stream *strm = (mz_stream *)stream;
|
||||
if (strm == NULL || strm->vtbl == NULL || strm->vtbl->open == NULL)
|
||||
return MZ_STREAM_ERROR;
|
||||
return strm->vtbl->open(strm, path, mode);
|
||||
}
|
||||
|
||||
int32_t mz_stream_is_open(void *stream)
|
||||
{
|
||||
mz_stream *strm = (mz_stream *)stream;
|
||||
if (strm == NULL || strm->vtbl == NULL || strm->vtbl->is_open == NULL)
|
||||
return MZ_STREAM_ERROR;
|
||||
return strm->vtbl->is_open(strm);
|
||||
}
|
||||
|
||||
int32_t mz_stream_read(void *stream, void *buf, int32_t size)
|
||||
{
|
||||
mz_stream *strm = (mz_stream *)stream;
|
||||
if (strm == NULL || strm->vtbl == NULL || strm->vtbl->read == NULL)
|
||||
return MZ_PARAM_ERROR;
|
||||
if (mz_stream_is_open(stream) != MZ_OK)
|
||||
return MZ_STREAM_ERROR;
|
||||
return strm->vtbl->read(strm, buf, size);
|
||||
}
|
||||
|
||||
static int32_t mz_stream_read_value(void *stream, uint64_t *value, int32_t len)
|
||||
{
|
||||
uint8_t buf[8];
|
||||
int32_t n = 0;
|
||||
int32_t i = 0;
|
||||
|
||||
*value = 0;
|
||||
if (mz_stream_read(stream, buf, len) == len)
|
||||
{
|
||||
for (n = 0; n < len; n += 1, i += 8)
|
||||
*value += ((uint64_t)buf[n]) << i;
|
||||
}
|
||||
else if (mz_stream_error(stream))
|
||||
return MZ_STREAM_ERROR;
|
||||
else
|
||||
return MZ_END_OF_STREAM;
|
||||
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_stream_read_uint8(void *stream, uint8_t *value)
|
||||
{
|
||||
int32_t err = MZ_OK;
|
||||
uint64_t value64 = 0;
|
||||
|
||||
*value = 0;
|
||||
err = mz_stream_read_value(stream, &value64, sizeof(uint8_t));
|
||||
if (err == MZ_OK)
|
||||
*value = (uint8_t)value64;
|
||||
return err;
|
||||
}
|
||||
|
||||
int32_t mz_stream_read_uint16(void *stream, uint16_t *value)
|
||||
{
|
||||
int32_t err = MZ_OK;
|
||||
uint64_t value64 = 0;
|
||||
|
||||
*value = 0;
|
||||
err = mz_stream_read_value(stream, &value64, sizeof(uint16_t));
|
||||
if (err == MZ_OK)
|
||||
*value = (uint16_t)value64;
|
||||
return err;
|
||||
}
|
||||
|
||||
int32_t mz_stream_read_uint32(void *stream, uint32_t *value)
|
||||
{
|
||||
int32_t err = MZ_OK;
|
||||
uint64_t value64 = 0;
|
||||
|
||||
*value = 0;
|
||||
err = mz_stream_read_value(stream, &value64, sizeof(uint32_t));
|
||||
if (err == MZ_OK)
|
||||
*value = (uint32_t)value64;
|
||||
return err;
|
||||
}
|
||||
|
||||
int32_t mz_stream_read_int64(void *stream, int64_t *value)
|
||||
{
|
||||
return mz_stream_read_value(stream, (uint64_t *)value, sizeof(uint64_t));
|
||||
}
|
||||
|
||||
int32_t mz_stream_read_uint64(void *stream, uint64_t *value)
|
||||
{
|
||||
return mz_stream_read_value(stream, value, sizeof(uint64_t));
|
||||
}
|
||||
|
||||
int32_t mz_stream_write(void *stream, const void *buf, int32_t size)
|
||||
{
|
||||
mz_stream *strm = (mz_stream *)stream;
|
||||
if (size == 0)
|
||||
return size;
|
||||
if (strm == NULL || strm->vtbl == NULL || strm->vtbl->write == NULL)
|
||||
return MZ_PARAM_ERROR;
|
||||
if (mz_stream_is_open(stream) != MZ_OK)
|
||||
return MZ_STREAM_ERROR;
|
||||
return strm->vtbl->write(strm, buf, size);
|
||||
}
|
||||
|
||||
static int32_t mz_stream_write_value(void *stream, uint64_t value, int32_t len)
|
||||
{
|
||||
uint8_t buf[8];
|
||||
int32_t n = 0;
|
||||
|
||||
for (n = 0; n < len; n += 1)
|
||||
{
|
||||
buf[n] = (uint8_t)(value & 0xff);
|
||||
value >>= 8;
|
||||
}
|
||||
|
||||
if (value != 0)
|
||||
{
|
||||
/* Data overflow - hack for ZIP64 (X Roche) */
|
||||
for (n = 0; n < len; n += 1)
|
||||
buf[n] = 0xff;
|
||||
}
|
||||
|
||||
if (mz_stream_write(stream, buf, len) != len)
|
||||
return MZ_STREAM_ERROR;
|
||||
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_stream_write_uint8(void *stream, uint8_t value)
|
||||
{
|
||||
return mz_stream_write_value(stream, value, sizeof(uint8_t));
|
||||
}
|
||||
|
||||
int32_t mz_stream_write_uint16(void *stream, uint16_t value)
|
||||
{
|
||||
return mz_stream_write_value(stream, value, sizeof(uint16_t));
|
||||
}
|
||||
|
||||
int32_t mz_stream_write_uint32(void *stream, uint32_t value)
|
||||
{
|
||||
return mz_stream_write_value(stream, value, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
int32_t mz_stream_write_int64(void *stream, int64_t value)
|
||||
{
|
||||
return mz_stream_write_value(stream, (uint64_t)value, sizeof(uint64_t));
|
||||
}
|
||||
|
||||
int32_t mz_stream_write_uint64(void *stream, uint64_t value)
|
||||
{
|
||||
return mz_stream_write_value(stream, value, sizeof(uint64_t));
|
||||
}
|
||||
|
||||
int32_t mz_stream_copy(void *target, void *source, int32_t len)
|
||||
{
|
||||
return mz_stream_copy_stream(target, NULL, source, NULL, len);
|
||||
}
|
||||
|
||||
int32_t mz_stream_copy_to_end(void *target, void *source)
|
||||
{
|
||||
return mz_stream_copy_stream_to_end(target, NULL, source, NULL);
|
||||
}
|
||||
|
||||
int32_t mz_stream_copy_stream(void *target, mz_stream_write_cb write_cb, void *source,
|
||||
mz_stream_read_cb read_cb, int32_t len)
|
||||
{
|
||||
uint8_t buf[16384];
|
||||
int32_t bytes_to_copy = 0;
|
||||
int32_t read = 0;
|
||||
int32_t written = 0;
|
||||
|
||||
if (write_cb == NULL)
|
||||
write_cb = mz_stream_write;
|
||||
if (read_cb == NULL)
|
||||
read_cb = mz_stream_read;
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
bytes_to_copy = len;
|
||||
if (bytes_to_copy > (int32_t)sizeof(buf))
|
||||
bytes_to_copy = sizeof(buf);
|
||||
read = read_cb(source, buf, bytes_to_copy);
|
||||
if (read <= 0)
|
||||
return MZ_STREAM_ERROR;
|
||||
written = write_cb(target, buf, read);
|
||||
if (written != read)
|
||||
return MZ_STREAM_ERROR;
|
||||
len -= read;
|
||||
}
|
||||
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_stream_copy_stream_to_end(void *target, mz_stream_write_cb write_cb, void *source,
|
||||
mz_stream_read_cb read_cb)
|
||||
{
|
||||
uint8_t buf[16384];
|
||||
int32_t read = 0;
|
||||
int32_t written = 0;
|
||||
|
||||
if (write_cb == NULL)
|
||||
write_cb = mz_stream_write;
|
||||
if (read_cb == NULL)
|
||||
read_cb = mz_stream_read;
|
||||
|
||||
read = read_cb(source, buf, sizeof(buf));
|
||||
while (read > 0)
|
||||
{
|
||||
written = write_cb(target, buf, read);
|
||||
if (written != read)
|
||||
return MZ_STREAM_ERROR;
|
||||
read = read_cb(source, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
if (read < 0)
|
||||
return MZ_STREAM_ERROR;
|
||||
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int64_t mz_stream_tell(void *stream)
|
||||
{
|
||||
mz_stream *strm = (mz_stream *)stream;
|
||||
if (strm == NULL || strm->vtbl == NULL || strm->vtbl->tell == NULL)
|
||||
return MZ_PARAM_ERROR;
|
||||
if (mz_stream_is_open(stream) != MZ_OK)
|
||||
return MZ_STREAM_ERROR;
|
||||
return strm->vtbl->tell(strm);
|
||||
}
|
||||
|
||||
int32_t mz_stream_seek(void *stream, int64_t offset, int32_t origin)
|
||||
{
|
||||
mz_stream *strm = (mz_stream *)stream;
|
||||
if (strm == NULL || strm->vtbl == NULL || strm->vtbl->seek == NULL)
|
||||
return MZ_PARAM_ERROR;
|
||||
if (mz_stream_is_open(stream) != MZ_OK)
|
||||
return MZ_STREAM_ERROR;
|
||||
if (origin == MZ_SEEK_SET && offset < 0)
|
||||
return MZ_SEEK_ERROR;
|
||||
return strm->vtbl->seek(strm, offset, origin);
|
||||
}
|
||||
|
||||
int32_t mz_stream_find(void *stream, const void *find, int32_t find_size, int64_t max_seek, int64_t *position)
|
||||
{
|
||||
uint8_t buf[MZ_STREAM_FIND_SIZE];
|
||||
int32_t buf_pos = 0;
|
||||
int32_t read_size = sizeof(buf);
|
||||
int32_t read = 0;
|
||||
int64_t read_pos = 0;
|
||||
int64_t start_pos = 0;
|
||||
int64_t disk_pos = 0;
|
||||
int32_t i = 0;
|
||||
uint8_t first = 1;
|
||||
int32_t err = MZ_OK;
|
||||
|
||||
if (stream == NULL || find == NULL || position == NULL)
|
||||
return MZ_PARAM_ERROR;
|
||||
if (find_size < 0 || find_size >= (int32_t)sizeof(buf))
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
*position = -1;
|
||||
|
||||
start_pos = mz_stream_tell(stream);
|
||||
|
||||
while (read_pos < max_seek)
|
||||
{
|
||||
if (read_size > (int32_t)(max_seek - read_pos - buf_pos) && (max_seek - read_pos - buf_pos) < (int64_t)sizeof(buf))
|
||||
read_size = (int32_t)(max_seek - read_pos - buf_pos);
|
||||
|
||||
read = mz_stream_read(stream, buf + buf_pos, read_size);
|
||||
if ((read <= 0) || (read + buf_pos < find_size))
|
||||
break;
|
||||
|
||||
for (i = 0; i <= read + buf_pos - find_size; i += 1)
|
||||
{
|
||||
if (memcmp(&buf[i], find, find_size) != 0)
|
||||
continue;
|
||||
|
||||
disk_pos = mz_stream_tell(stream);
|
||||
|
||||
/* Seek to position on disk where the data was found */
|
||||
err = mz_stream_seek(stream, disk_pos - ((int64_t)read + buf_pos - i), MZ_SEEK_SET);
|
||||
if (err != MZ_OK)
|
||||
return MZ_EXIST_ERROR;
|
||||
|
||||
*position = start_pos + read_pos + i;
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
if (first)
|
||||
{
|
||||
read -= find_size;
|
||||
read_size -= find_size;
|
||||
buf_pos = find_size;
|
||||
first = 0;
|
||||
}
|
||||
|
||||
memmove(buf, buf + read, find_size);
|
||||
read_pos += read;
|
||||
}
|
||||
|
||||
return MZ_EXIST_ERROR;
|
||||
}
|
||||
|
||||
int32_t mz_stream_find_reverse(void *stream, const void *find, int32_t find_size, int64_t max_seek, int64_t *position)
|
||||
{
|
||||
uint8_t buf[MZ_STREAM_FIND_SIZE];
|
||||
int32_t buf_pos = 0;
|
||||
int32_t read_size = MZ_STREAM_FIND_SIZE;
|
||||
int64_t read_pos = 0;
|
||||
int32_t read = 0;
|
||||
int64_t start_pos = 0;
|
||||
int64_t disk_pos = 0;
|
||||
uint8_t first = 1;
|
||||
int32_t i = 0;
|
||||
int32_t err = MZ_OK;
|
||||
|
||||
if (stream == NULL || find == NULL || position == NULL)
|
||||
return MZ_PARAM_ERROR;
|
||||
if (find_size < 0 || find_size >= (int32_t)sizeof(buf))
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
*position = -1;
|
||||
|
||||
start_pos = mz_stream_tell(stream);
|
||||
|
||||
while (read_pos < max_seek)
|
||||
{
|
||||
if (read_size > (int32_t)(max_seek - read_pos) && (max_seek - read_pos) < (int64_t)sizeof(buf))
|
||||
read_size = (int32_t)(max_seek - read_pos);
|
||||
|
||||
if (mz_stream_seek(stream, start_pos - (read_pos + read_size), MZ_SEEK_SET) != MZ_OK)
|
||||
break;
|
||||
read = mz_stream_read(stream, buf, read_size);
|
||||
if ((read <= 0) || (read + buf_pos < find_size))
|
||||
break;
|
||||
if (read + buf_pos < MZ_STREAM_FIND_SIZE)
|
||||
memmove(buf + MZ_STREAM_FIND_SIZE - (read + buf_pos), buf, read);
|
||||
|
||||
for (i = find_size; i <= (read + buf_pos); i += 1)
|
||||
{
|
||||
if (memcmp(&buf[MZ_STREAM_FIND_SIZE - i], find, find_size) != 0)
|
||||
continue;
|
||||
|
||||
disk_pos = mz_stream_tell(stream);
|
||||
|
||||
/* Seek to position on disk where the data was found */
|
||||
err = mz_stream_seek(stream, disk_pos + buf_pos - i, MZ_SEEK_SET);
|
||||
if (err != MZ_OK)
|
||||
return MZ_EXIST_ERROR;
|
||||
|
||||
*position = start_pos - (read_pos - buf_pos + i);
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
if (first)
|
||||
{
|
||||
read -= find_size;
|
||||
read_size -= find_size;
|
||||
buf_pos = find_size;
|
||||
first = 0;
|
||||
}
|
||||
|
||||
if (read == 0)
|
||||
break;
|
||||
|
||||
memmove(buf + read_size, buf, find_size);
|
||||
read_pos += read;
|
||||
}
|
||||
|
||||
return MZ_EXIST_ERROR;
|
||||
}
|
||||
|
||||
int32_t mz_stream_close(void *stream)
|
||||
{
|
||||
mz_stream *strm = (mz_stream *)stream;
|
||||
if (strm == NULL || strm->vtbl == NULL || strm->vtbl->close == NULL)
|
||||
return MZ_PARAM_ERROR;
|
||||
if (mz_stream_is_open(stream) != MZ_OK)
|
||||
return MZ_STREAM_ERROR;
|
||||
return strm->vtbl->close(strm);
|
||||
}
|
||||
|
||||
int32_t mz_stream_error(void *stream)
|
||||
{
|
||||
mz_stream *strm = (mz_stream *)stream;
|
||||
if (strm == NULL || strm->vtbl == NULL || strm->vtbl->error == NULL)
|
||||
return MZ_PARAM_ERROR;
|
||||
return strm->vtbl->error(strm);
|
||||
}
|
||||
|
||||
int32_t mz_stream_set_base(void *stream, void *base)
|
||||
{
|
||||
mz_stream *strm = (mz_stream *)stream;
|
||||
strm->base = (mz_stream *)base;
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
void* mz_stream_get_interface(void *stream)
|
||||
{
|
||||
mz_stream *strm = (mz_stream *)stream;
|
||||
if (strm == NULL || strm->vtbl == NULL)
|
||||
return NULL;
|
||||
return (void *)strm->vtbl;
|
||||
}
|
||||
|
||||
int32_t mz_stream_get_prop_int64(void *stream, int32_t prop, int64_t *value)
|
||||
{
|
||||
mz_stream *strm = (mz_stream *)stream;
|
||||
if (strm == NULL || strm->vtbl == NULL || strm->vtbl->get_prop_int64 == NULL)
|
||||
return MZ_PARAM_ERROR;
|
||||
return strm->vtbl->get_prop_int64(stream, prop, value);
|
||||
}
|
||||
|
||||
int32_t mz_stream_set_prop_int64(void *stream, int32_t prop, int64_t value)
|
||||
{
|
||||
mz_stream *strm = (mz_stream *)stream;
|
||||
if (strm == NULL || strm->vtbl == NULL || strm->vtbl->set_prop_int64 == NULL)
|
||||
return MZ_PARAM_ERROR;
|
||||
return strm->vtbl->set_prop_int64(stream, prop, value);
|
||||
}
|
||||
|
||||
void *mz_stream_create(void **stream, mz_stream_vtbl *vtbl)
|
||||
{
|
||||
if (stream == NULL)
|
||||
return NULL;
|
||||
if (vtbl == NULL || vtbl->create == NULL)
|
||||
return NULL;
|
||||
return vtbl->create(stream);
|
||||
}
|
||||
|
||||
void mz_stream_delete(void **stream)
|
||||
{
|
||||
mz_stream *strm = NULL;
|
||||
if (stream == NULL)
|
||||
return;
|
||||
strm = (mz_stream *)*stream;
|
||||
if (strm != NULL && strm->vtbl != NULL && strm->vtbl->destroy != NULL)
|
||||
strm->vtbl->destroy(stream);
|
||||
*stream = NULL;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
typedef struct mz_stream_raw_s {
|
||||
mz_stream stream;
|
||||
int64_t total_in;
|
||||
int64_t total_out;
|
||||
int64_t max_total_in;
|
||||
} mz_stream_raw;
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_stream_raw_open(void *stream, const char *path, int32_t mode)
|
||||
{
|
||||
MZ_UNUSED(stream);
|
||||
MZ_UNUSED(path);
|
||||
MZ_UNUSED(mode);
|
||||
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_stream_raw_is_open(void *stream)
|
||||
{
|
||||
mz_stream_raw *raw = (mz_stream_raw *)stream;
|
||||
return mz_stream_is_open(raw->stream.base);
|
||||
}
|
||||
|
||||
int32_t mz_stream_raw_read(void *stream, void *buf, int32_t size)
|
||||
{
|
||||
mz_stream_raw *raw = (mz_stream_raw *)stream;
|
||||
int32_t bytes_to_read = size;
|
||||
int32_t read = 0;
|
||||
|
||||
if (raw->max_total_in > 0)
|
||||
{
|
||||
if ((int64_t)bytes_to_read > (raw->max_total_in - raw->total_in))
|
||||
bytes_to_read = (int32_t)(raw->max_total_in - raw->total_in);
|
||||
}
|
||||
|
||||
read = mz_stream_read(raw->stream.base, buf, bytes_to_read);
|
||||
|
||||
if (read > 0)
|
||||
{
|
||||
raw->total_in += read;
|
||||
raw->total_out += read;
|
||||
}
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
int32_t mz_stream_raw_write(void *stream, const void *buf, int32_t size)
|
||||
{
|
||||
mz_stream_raw *raw = (mz_stream_raw *)stream;
|
||||
int32_t written = 0;
|
||||
|
||||
written = mz_stream_write(raw->stream.base, buf, size);
|
||||
|
||||
if (written > 0)
|
||||
{
|
||||
raw->total_out += written;
|
||||
raw->total_in += written;
|
||||
}
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
int64_t mz_stream_raw_tell(void *stream)
|
||||
{
|
||||
mz_stream_raw *raw = (mz_stream_raw *)stream;
|
||||
return mz_stream_tell(raw->stream.base);
|
||||
}
|
||||
|
||||
int32_t mz_stream_raw_seek(void *stream, int64_t offset, int32_t origin)
|
||||
{
|
||||
mz_stream_raw *raw = (mz_stream_raw *)stream;
|
||||
return mz_stream_seek(raw->stream.base, offset, origin);
|
||||
}
|
||||
|
||||
int32_t mz_stream_raw_close(void *stream)
|
||||
{
|
||||
MZ_UNUSED(stream);
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_stream_raw_error(void *stream)
|
||||
{
|
||||
mz_stream_raw *raw = (mz_stream_raw *)stream;
|
||||
return mz_stream_error(raw->stream.base);
|
||||
}
|
||||
|
||||
int32_t mz_stream_raw_get_prop_int64(void *stream, int32_t prop, int64_t *value)
|
||||
{
|
||||
mz_stream_raw *raw = (mz_stream_raw *)stream;
|
||||
switch (prop)
|
||||
{
|
||||
case MZ_STREAM_PROP_TOTAL_IN:
|
||||
*value = raw->total_in;
|
||||
return MZ_OK;
|
||||
case MZ_STREAM_PROP_TOTAL_OUT:
|
||||
*value = raw->total_out;
|
||||
return MZ_OK;
|
||||
}
|
||||
return MZ_EXIST_ERROR;
|
||||
}
|
||||
|
||||
int32_t mz_stream_raw_set_prop_int64(void *stream, int32_t prop, int64_t value)
|
||||
{
|
||||
mz_stream_raw *raw = (mz_stream_raw *)stream;
|
||||
switch (prop)
|
||||
{
|
||||
case MZ_STREAM_PROP_TOTAL_IN_MAX:
|
||||
raw->max_total_in = value;
|
||||
return MZ_OK;
|
||||
}
|
||||
return MZ_EXIST_ERROR;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
static mz_stream_vtbl mz_stream_raw_vtbl = {
|
||||
mz_stream_raw_open,
|
||||
mz_stream_raw_is_open,
|
||||
mz_stream_raw_read,
|
||||
mz_stream_raw_write,
|
||||
mz_stream_raw_tell,
|
||||
mz_stream_raw_seek,
|
||||
mz_stream_raw_close,
|
||||
mz_stream_raw_error,
|
||||
mz_stream_raw_create,
|
||||
mz_stream_raw_delete,
|
||||
mz_stream_raw_get_prop_int64,
|
||||
mz_stream_raw_set_prop_int64
|
||||
};
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
void *mz_stream_raw_create(void **stream)
|
||||
{
|
||||
mz_stream_raw *raw = NULL;
|
||||
|
||||
raw = (mz_stream_raw *)MZ_ALLOC(sizeof(mz_stream_raw));
|
||||
if (raw != NULL)
|
||||
{
|
||||
memset(raw, 0, sizeof(mz_stream_raw));
|
||||
raw->stream.vtbl = &mz_stream_raw_vtbl;
|
||||
}
|
||||
if (stream != NULL)
|
||||
*stream = raw;
|
||||
|
||||
return raw;
|
||||
}
|
||||
|
||||
void mz_stream_raw_delete(void **stream)
|
||||
{
|
||||
mz_stream_raw *raw = NULL;
|
||||
if (stream == NULL)
|
||||
return;
|
||||
raw = (mz_stream_raw *)*stream;
|
||||
if (raw != NULL)
|
||||
MZ_FREE(raw);
|
||||
*stream = NULL;
|
||||
}
|
134
third-party/ZipArchive/Sources/minizip/mz_strm.h
vendored
Normal file
134
third-party/ZipArchive/Sources/minizip/mz_strm.h
vendored
Normal file
@ -0,0 +1,134 @@
|
||||
/* mz_strm.h -- Stream interface
|
||||
Version 2.9.2, February 12, 2020
|
||||
part of the MiniZip project
|
||||
|
||||
Copyright (C) 2010-2020 Nathan Moinvaziri
|
||||
https://github.com/nmoinvaz/minizip
|
||||
|
||||
This program is distributed under the terms of the same license as zlib.
|
||||
See the accompanying LICENSE file for the full text of the license.
|
||||
*/
|
||||
|
||||
#ifndef MZ_STREAM_H
|
||||
#define MZ_STREAM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#define MZ_STREAM_PROP_TOTAL_IN (1)
|
||||
#define MZ_STREAM_PROP_TOTAL_IN_MAX (2)
|
||||
#define MZ_STREAM_PROP_TOTAL_OUT (3)
|
||||
#define MZ_STREAM_PROP_TOTAL_OUT_MAX (4)
|
||||
#define MZ_STREAM_PROP_HEADER_SIZE (5)
|
||||
#define MZ_STREAM_PROP_FOOTER_SIZE (6)
|
||||
#define MZ_STREAM_PROP_DISK_SIZE (7)
|
||||
#define MZ_STREAM_PROP_DISK_NUMBER (8)
|
||||
#define MZ_STREAM_PROP_COMPRESS_LEVEL (9)
|
||||
#define MZ_STREAM_PROP_COMPRESS_ALGORITHM (10)
|
||||
#define MZ_STREAM_PROP_COMPRESS_WINDOW (11)
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
typedef int32_t (*mz_stream_open_cb) (void *stream, const char *path, int32_t mode);
|
||||
typedef int32_t (*mz_stream_is_open_cb) (void *stream);
|
||||
typedef int32_t (*mz_stream_read_cb) (void *stream, void *buf, int32_t size);
|
||||
typedef int32_t (*mz_stream_write_cb) (void *stream, const void *buf, int32_t size);
|
||||
typedef int64_t (*mz_stream_tell_cb) (void *stream);
|
||||
typedef int32_t (*mz_stream_seek_cb) (void *stream, int64_t offset, int32_t origin);
|
||||
typedef int32_t (*mz_stream_close_cb) (void *stream);
|
||||
typedef int32_t (*mz_stream_error_cb) (void *stream);
|
||||
typedef void* (*mz_stream_create_cb) (void **stream);
|
||||
typedef void (*mz_stream_destroy_cb) (void **stream);
|
||||
|
||||
typedef int32_t (*mz_stream_get_prop_int64_cb) (void *stream, int32_t prop, int64_t *value);
|
||||
typedef int32_t (*mz_stream_set_prop_int64_cb) (void *stream, int32_t prop, int64_t value);
|
||||
|
||||
typedef int32_t (*mz_stream_find_cb) (void *stream, const void *find, int32_t find_size,
|
||||
int64_t max_seek, int64_t *position);
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
typedef struct mz_stream_vtbl_s
|
||||
{
|
||||
mz_stream_open_cb open;
|
||||
mz_stream_is_open_cb is_open;
|
||||
mz_stream_read_cb read;
|
||||
mz_stream_write_cb write;
|
||||
mz_stream_tell_cb tell;
|
||||
mz_stream_seek_cb seek;
|
||||
mz_stream_close_cb close;
|
||||
mz_stream_error_cb error;
|
||||
mz_stream_create_cb create;
|
||||
mz_stream_destroy_cb destroy;
|
||||
|
||||
mz_stream_get_prop_int64_cb get_prop_int64;
|
||||
mz_stream_set_prop_int64_cb set_prop_int64;
|
||||
} mz_stream_vtbl;
|
||||
|
||||
typedef struct mz_stream_s {
|
||||
mz_stream_vtbl *vtbl;
|
||||
struct mz_stream_s *base;
|
||||
} mz_stream;
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_stream_open(void *stream, const char *path, int32_t mode);
|
||||
int32_t mz_stream_is_open(void *stream);
|
||||
int32_t mz_stream_read(void *stream, void *buf, int32_t size);
|
||||
int32_t mz_stream_read_uint8(void *stream, uint8_t *value);
|
||||
int32_t mz_stream_read_uint16(void *stream, uint16_t *value);
|
||||
int32_t mz_stream_read_uint32(void *stream, uint32_t *value);
|
||||
int32_t mz_stream_read_int64(void *stream, int64_t *value);
|
||||
int32_t mz_stream_read_uint64(void *stream, uint64_t *value);
|
||||
int32_t mz_stream_write(void *stream, const void *buf, int32_t size);
|
||||
int32_t mz_stream_write_uint8(void *stream, uint8_t value);
|
||||
int32_t mz_stream_write_uint16(void *stream, uint16_t value);
|
||||
int32_t mz_stream_write_uint32(void *stream, uint32_t value);
|
||||
int32_t mz_stream_write_int64(void *stream, int64_t value);
|
||||
int32_t mz_stream_write_uint64(void *stream, uint64_t value);
|
||||
int32_t mz_stream_copy(void *target, void *source, int32_t len);
|
||||
int32_t mz_stream_copy_to_end(void *target, void *source);
|
||||
int32_t mz_stream_copy_stream(void *target, mz_stream_write_cb write_cb, void *source, mz_stream_read_cb read_cb, int32_t len);
|
||||
int32_t mz_stream_copy_stream_to_end(void *target, mz_stream_write_cb write_cb, void *source, mz_stream_read_cb read_cb);
|
||||
int64_t mz_stream_tell(void *stream);
|
||||
int32_t mz_stream_seek(void *stream, int64_t offset, int32_t origin);
|
||||
int32_t mz_stream_find(void *stream, const void *find, int32_t find_size, int64_t max_seek, int64_t *position);
|
||||
int32_t mz_stream_find_reverse(void *stream, const void *find, int32_t find_size, int64_t max_seek, int64_t *position);
|
||||
int32_t mz_stream_close(void *stream);
|
||||
int32_t mz_stream_error(void *stream);
|
||||
|
||||
int32_t mz_stream_set_base(void *stream, void *base);
|
||||
void* mz_stream_get_interface(void *stream);
|
||||
int32_t mz_stream_get_prop_int64(void *stream, int32_t prop, int64_t *value);
|
||||
int32_t mz_stream_set_prop_int64(void *stream, int32_t prop, int64_t value);
|
||||
|
||||
void* mz_stream_create(void **stream, mz_stream_vtbl *vtbl);
|
||||
void mz_stream_delete(void **stream);
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_stream_raw_open(void *stream, const char *filename, int32_t mode);
|
||||
int32_t mz_stream_raw_is_open(void *stream);
|
||||
int32_t mz_stream_raw_read(void *stream, void *buf, int32_t size);
|
||||
int32_t mz_stream_raw_write(void *stream, const void *buf, int32_t size);
|
||||
int64_t mz_stream_raw_tell(void *stream);
|
||||
int32_t mz_stream_raw_seek(void *stream, int64_t offset, int32_t origin);
|
||||
int32_t mz_stream_raw_close(void *stream);
|
||||
int32_t mz_stream_raw_error(void *stream);
|
||||
|
||||
int32_t mz_stream_raw_get_prop_int64(void *stream, int32_t prop, int64_t *value);
|
||||
int32_t mz_stream_raw_set_prop_int64(void *stream, int32_t prop, int64_t value);
|
||||
|
||||
void* mz_stream_raw_create(void **stream);
|
||||
void mz_stream_raw_delete(void **stream);
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
416
third-party/ZipArchive/Sources/minizip/mz_strm_buf.c
vendored
Normal file
416
third-party/ZipArchive/Sources/minizip/mz_strm_buf.c
vendored
Normal file
@ -0,0 +1,416 @@
|
||||
/* mz_strm_buf.c -- Stream for buffering reads/writes
|
||||
Version 2.9.2, February 12, 2020
|
||||
part of the MiniZip project
|
||||
|
||||
This version of ioapi is designed to buffer IO.
|
||||
|
||||
Copyright (C) 2010-2020 Nathan Moinvaziri
|
||||
https://github.com/nmoinvaz/minizip
|
||||
|
||||
This program is distributed under the terms of the same license as zlib.
|
||||
See the accompanying LICENSE file for the full text of the license.
|
||||
*/
|
||||
|
||||
#include "mz.h"
|
||||
#include "mz_strm.h"
|
||||
#include "mz_strm_buf.h"
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
static mz_stream_vtbl mz_stream_buffered_vtbl = {
|
||||
mz_stream_buffered_open,
|
||||
mz_stream_buffered_is_open,
|
||||
mz_stream_buffered_read,
|
||||
mz_stream_buffered_write,
|
||||
mz_stream_buffered_tell,
|
||||
mz_stream_buffered_seek,
|
||||
mz_stream_buffered_close,
|
||||
mz_stream_buffered_error,
|
||||
mz_stream_buffered_create,
|
||||
mz_stream_buffered_delete,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
typedef struct mz_stream_buffered_s {
|
||||
mz_stream stream;
|
||||
int32_t error;
|
||||
char readbuf[INT16_MAX];
|
||||
int32_t readbuf_len;
|
||||
int32_t readbuf_pos;
|
||||
int32_t readbuf_hits;
|
||||
int32_t readbuf_misses;
|
||||
char writebuf[INT16_MAX];
|
||||
int32_t writebuf_len;
|
||||
int32_t writebuf_pos;
|
||||
int32_t writebuf_hits;
|
||||
int32_t writebuf_misses;
|
||||
int64_t position;
|
||||
} mz_stream_buffered;
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#if 0
|
||||
# define mz_stream_buffered_print printf
|
||||
#else
|
||||
# define mz_stream_buffered_print(fmt,...)
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
static int32_t mz_stream_buffered_reset(void *stream)
|
||||
{
|
||||
mz_stream_buffered *buffered = (mz_stream_buffered *)stream;
|
||||
|
||||
buffered->readbuf_len = 0;
|
||||
buffered->readbuf_pos = 0;
|
||||
buffered->writebuf_len = 0;
|
||||
buffered->writebuf_pos = 0;
|
||||
buffered->position = 0;
|
||||
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_stream_buffered_open(void *stream, const char *path, int32_t mode)
|
||||
{
|
||||
mz_stream_buffered *buffered = (mz_stream_buffered *)stream;
|
||||
mz_stream_buffered_print("Buffered - Open (mode %" PRId32 ")\n", mode);
|
||||
mz_stream_buffered_reset(buffered);
|
||||
return mz_stream_open(buffered->stream.base, path, mode);
|
||||
}
|
||||
|
||||
int32_t mz_stream_buffered_is_open(void *stream)
|
||||
{
|
||||
mz_stream_buffered *buffered = (mz_stream_buffered *)stream;
|
||||
return mz_stream_is_open(buffered->stream.base);
|
||||
}
|
||||
|
||||
static int32_t mz_stream_buffered_flush(void *stream, int32_t *written)
|
||||
{
|
||||
mz_stream_buffered *buffered = (mz_stream_buffered *)stream;
|
||||
int32_t total_bytes_written = 0;
|
||||
int32_t bytes_to_write = buffered->writebuf_len;
|
||||
int32_t bytes_left_to_write = buffered->writebuf_len;
|
||||
int32_t bytes_written = 0;
|
||||
|
||||
*written = 0;
|
||||
|
||||
while (bytes_left_to_write > 0)
|
||||
{
|
||||
bytes_written = mz_stream_write(buffered->stream.base,
|
||||
buffered->writebuf + (bytes_to_write - bytes_left_to_write), bytes_left_to_write);
|
||||
|
||||
if (bytes_written != bytes_left_to_write)
|
||||
return MZ_WRITE_ERROR;
|
||||
|
||||
buffered->writebuf_misses += 1;
|
||||
|
||||
mz_stream_buffered_print("Buffered - Write flush (%" PRId32 ":%" PRId32 " len %" PRId32 ")\n",
|
||||
bytes_to_write, bytes_left_to_write, buffered->writebuf_len);
|
||||
|
||||
total_bytes_written += bytes_written;
|
||||
bytes_left_to_write -= bytes_written;
|
||||
buffered->position += bytes_written;
|
||||
}
|
||||
|
||||
buffered->writebuf_len = 0;
|
||||
buffered->writebuf_pos = 0;
|
||||
|
||||
*written = total_bytes_written;
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_stream_buffered_read(void *stream, void *buf, int32_t size)
|
||||
{
|
||||
mz_stream_buffered *buffered = (mz_stream_buffered *)stream;
|
||||
int32_t buf_len = 0;
|
||||
int32_t bytes_to_read = 0;
|
||||
int32_t bytes_to_copy = 0;
|
||||
int32_t bytes_left_to_read = size;
|
||||
int32_t bytes_read = 0;
|
||||
|
||||
mz_stream_buffered_print("Buffered - Read (size %" PRId32 " pos %" PRId64 ")\n", size, buffered->position);
|
||||
|
||||
if (buffered->writebuf_len > 0)
|
||||
{
|
||||
mz_stream_buffered_print("Buffered - Switch from write to read, not yet supported (pos %" PRId64 ")\n",
|
||||
buffered->position);
|
||||
}
|
||||
|
||||
while (bytes_left_to_read > 0)
|
||||
{
|
||||
if ((buffered->readbuf_len == 0) || (buffered->readbuf_pos == buffered->readbuf_len))
|
||||
{
|
||||
if (buffered->readbuf_len == sizeof(buffered->readbuf))
|
||||
{
|
||||
buffered->readbuf_pos = 0;
|
||||
buffered->readbuf_len = 0;
|
||||
}
|
||||
|
||||
bytes_to_read = (int32_t)sizeof(buffered->readbuf) - (buffered->readbuf_len - buffered->readbuf_pos);
|
||||
bytes_read = mz_stream_read(buffered->stream.base, buffered->readbuf + buffered->readbuf_pos, bytes_to_read);
|
||||
if (bytes_read < 0)
|
||||
return bytes_read;
|
||||
|
||||
buffered->readbuf_misses += 1;
|
||||
buffered->readbuf_len += bytes_read;
|
||||
buffered->position += bytes_read;
|
||||
|
||||
mz_stream_buffered_print("Buffered - Filled (read %" PRId32 "/%" PRId32 " buf %" PRId32 ":%" PRId32 " pos %" PRId64 ")\n",
|
||||
bytes_read, bytes_to_read, buffered->readbuf_pos, buffered->readbuf_len, buffered->position);
|
||||
|
||||
if (bytes_read == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if ((buffered->readbuf_len - buffered->readbuf_pos) > 0)
|
||||
{
|
||||
bytes_to_copy = buffered->readbuf_len - buffered->readbuf_pos;
|
||||
if (bytes_to_copy > bytes_left_to_read)
|
||||
bytes_to_copy = bytes_left_to_read;
|
||||
|
||||
memcpy((char *)buf + buf_len, buffered->readbuf + buffered->readbuf_pos, bytes_to_copy);
|
||||
|
||||
buf_len += bytes_to_copy;
|
||||
bytes_left_to_read -= bytes_to_copy;
|
||||
|
||||
buffered->readbuf_hits += 1;
|
||||
buffered->readbuf_pos += bytes_to_copy;
|
||||
|
||||
mz_stream_buffered_print("Buffered - Emptied (copied %" PRId32 " remaining %" PRId32 " buf %" PRId32 ":%" PRId32 " pos %" PRId64 ")\n",
|
||||
bytes_to_copy, bytes_left_to_read, buffered->readbuf_pos, buffered->readbuf_len, buffered->position);
|
||||
}
|
||||
}
|
||||
|
||||
return size - bytes_left_to_read;
|
||||
}
|
||||
|
||||
int32_t mz_stream_buffered_write(void *stream, const void *buf, int32_t size)
|
||||
{
|
||||
mz_stream_buffered *buffered = (mz_stream_buffered *)stream;
|
||||
int32_t bytes_to_write = size;
|
||||
int32_t bytes_left_to_write = size;
|
||||
int32_t bytes_to_copy = 0;
|
||||
int32_t bytes_used = 0;
|
||||
int32_t bytes_flushed = 0;
|
||||
int32_t err = MZ_OK;
|
||||
|
||||
|
||||
mz_stream_buffered_print("Buffered - Write (size %" PRId32 " len %" PRId32 " pos %" PRId64 ")\n",
|
||||
size, buffered->writebuf_len, buffered->position);
|
||||
|
||||
if (buffered->readbuf_len > 0)
|
||||
{
|
||||
buffered->position -= buffered->readbuf_len;
|
||||
buffered->position += buffered->readbuf_pos;
|
||||
|
||||
buffered->readbuf_len = 0;
|
||||
buffered->readbuf_pos = 0;
|
||||
|
||||
mz_stream_buffered_print("Buffered - Switch from read to write (pos %" PRId64 ")\n", buffered->position);
|
||||
|
||||
err = mz_stream_seek(buffered->stream.base, buffered->position, MZ_SEEK_SET);
|
||||
if (err != MZ_OK)
|
||||
return err;
|
||||
}
|
||||
|
||||
while (bytes_left_to_write > 0)
|
||||
{
|
||||
bytes_used = buffered->writebuf_len;
|
||||
if (bytes_used > buffered->writebuf_pos)
|
||||
bytes_used = buffered->writebuf_pos;
|
||||
bytes_to_copy = (int32_t)sizeof(buffered->writebuf) - bytes_used;
|
||||
if (bytes_to_copy > bytes_left_to_write)
|
||||
bytes_to_copy = bytes_left_to_write;
|
||||
|
||||
if (bytes_to_copy == 0)
|
||||
{
|
||||
err = mz_stream_buffered_flush(stream, &bytes_flushed);
|
||||
if (err != MZ_OK)
|
||||
return err;
|
||||
if (bytes_flushed == 0)
|
||||
return 0;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(buffered->writebuf + buffered->writebuf_pos,
|
||||
(const char *)buf + (bytes_to_write - bytes_left_to_write), bytes_to_copy);
|
||||
|
||||
mz_stream_buffered_print("Buffered - Write copy (remaining %" PRId32 " write %" PRId32 ":%" PRId32 " len %" PRId32 ")\n",
|
||||
bytes_to_copy, bytes_to_write, bytes_left_to_write, buffered->writebuf_len);
|
||||
|
||||
bytes_left_to_write -= bytes_to_copy;
|
||||
|
||||
buffered->writebuf_pos += bytes_to_copy;
|
||||
buffered->writebuf_hits += 1;
|
||||
if (buffered->writebuf_pos > buffered->writebuf_len)
|
||||
buffered->writebuf_len += buffered->writebuf_pos - buffered->writebuf_len;
|
||||
}
|
||||
|
||||
return size - bytes_left_to_write;
|
||||
}
|
||||
|
||||
int64_t mz_stream_buffered_tell(void *stream)
|
||||
{
|
||||
mz_stream_buffered *buffered = (mz_stream_buffered *)stream;
|
||||
int64_t position = mz_stream_tell(buffered->stream.base);
|
||||
|
||||
buffered->position = position;
|
||||
|
||||
mz_stream_buffered_print("Buffered - Tell (pos %" PRId64 " readpos %" PRId32 " writepos %" PRId32 ")\n",
|
||||
buffered->position, buffered->readbuf_pos, buffered->writebuf_pos);
|
||||
|
||||
if (buffered->readbuf_len > 0)
|
||||
position -= ((int64_t)buffered->readbuf_len - buffered->readbuf_pos);
|
||||
if (buffered->writebuf_len > 0)
|
||||
position += buffered->writebuf_pos;
|
||||
return position;
|
||||
}
|
||||
|
||||
int32_t mz_stream_buffered_seek(void *stream, int64_t offset, int32_t origin)
|
||||
{
|
||||
mz_stream_buffered *buffered = (mz_stream_buffered *)stream;
|
||||
int32_t bytes_flushed = 0;
|
||||
int32_t err = MZ_OK;
|
||||
|
||||
mz_stream_buffered_print("Buffered - Seek (origin %" PRId32 " offset %" PRId64 " pos %" PRId64 ")\n",
|
||||
origin, offset, buffered->position);
|
||||
|
||||
switch (origin)
|
||||
{
|
||||
case MZ_SEEK_SET:
|
||||
|
||||
if (buffered->writebuf_len > 0)
|
||||
{
|
||||
if ((offset >= buffered->position) && (offset <= buffered->position + buffered->writebuf_len))
|
||||
{
|
||||
buffered->writebuf_pos = (int32_t)(offset - buffered->position);
|
||||
return MZ_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if ((buffered->readbuf_len > 0) && (offset < buffered->position) &&
|
||||
(offset >= buffered->position - buffered->readbuf_len))
|
||||
{
|
||||
buffered->readbuf_pos = (int32_t)(offset - (buffered->position - buffered->readbuf_len));
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
err = mz_stream_buffered_flush(stream, &bytes_flushed);
|
||||
if (err != MZ_OK)
|
||||
return err;
|
||||
|
||||
buffered->position = offset;
|
||||
break;
|
||||
|
||||
case MZ_SEEK_CUR:
|
||||
|
||||
if (buffered->readbuf_len > 0)
|
||||
{
|
||||
if (offset <= ((int64_t)buffered->readbuf_len - buffered->readbuf_pos))
|
||||
{
|
||||
buffered->readbuf_pos += (uint32_t)offset;
|
||||
return MZ_OK;
|
||||
}
|
||||
offset -= ((int64_t)buffered->readbuf_len - buffered->readbuf_pos);
|
||||
buffered->position += offset;
|
||||
}
|
||||
if (buffered->writebuf_len > 0)
|
||||
{
|
||||
if (offset <= ((int64_t)buffered->writebuf_len - buffered->writebuf_pos))
|
||||
{
|
||||
buffered->writebuf_pos += (uint32_t)offset;
|
||||
return MZ_OK;
|
||||
}
|
||||
/* offset -= (buffered->writebuf_len - buffered->writebuf_pos); */
|
||||
}
|
||||
|
||||
err = mz_stream_buffered_flush(stream, &bytes_flushed);
|
||||
if (err != MZ_OK)
|
||||
return err;
|
||||
|
||||
break;
|
||||
|
||||
case MZ_SEEK_END:
|
||||
|
||||
if (buffered->writebuf_len > 0)
|
||||
{
|
||||
buffered->writebuf_pos = buffered->writebuf_len;
|
||||
return MZ_OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
buffered->readbuf_len = 0;
|
||||
buffered->readbuf_pos = 0;
|
||||
buffered->writebuf_len = 0;
|
||||
buffered->writebuf_pos = 0;
|
||||
|
||||
return mz_stream_seek(buffered->stream.base, offset, origin);
|
||||
}
|
||||
|
||||
int32_t mz_stream_buffered_close(void *stream)
|
||||
{
|
||||
mz_stream_buffered *buffered = (mz_stream_buffered *)stream;
|
||||
int32_t bytes_flushed = 0;
|
||||
|
||||
mz_stream_buffered_flush(stream, &bytes_flushed);
|
||||
mz_stream_buffered_print("Buffered - Close (flushed %" PRId32 ")\n", bytes_flushed);
|
||||
|
||||
if (buffered->readbuf_hits + buffered->readbuf_misses > 0)
|
||||
{
|
||||
mz_stream_buffered_print("Buffered - Read efficiency %.02f%%\n",
|
||||
(buffered->readbuf_hits / ((float)buffered->readbuf_hits + buffered->readbuf_misses)) * 100);
|
||||
}
|
||||
|
||||
if (buffered->writebuf_hits + buffered->writebuf_misses > 0)
|
||||
{
|
||||
mz_stream_buffered_print("Buffered - Write efficiency %.02f%%\n",
|
||||
(buffered->writebuf_hits / ((float)buffered->writebuf_hits + buffered->writebuf_misses)) * 100);
|
||||
}
|
||||
|
||||
mz_stream_buffered_reset(buffered);
|
||||
|
||||
return mz_stream_close(buffered->stream.base);
|
||||
}
|
||||
|
||||
int32_t mz_stream_buffered_error(void *stream)
|
||||
{
|
||||
mz_stream_buffered *buffered = (mz_stream_buffered *)stream;
|
||||
return mz_stream_error(buffered->stream.base);
|
||||
}
|
||||
|
||||
void *mz_stream_buffered_create(void **stream)
|
||||
{
|
||||
mz_stream_buffered *buffered = NULL;
|
||||
|
||||
buffered = (mz_stream_buffered *)MZ_ALLOC(sizeof(mz_stream_buffered));
|
||||
if (buffered != NULL)
|
||||
{
|
||||
memset(buffered, 0, sizeof(mz_stream_buffered));
|
||||
buffered->stream.vtbl = &mz_stream_buffered_vtbl;
|
||||
}
|
||||
if (stream != NULL)
|
||||
*stream = buffered;
|
||||
|
||||
return buffered;
|
||||
}
|
||||
|
||||
void mz_stream_buffered_delete(void **stream)
|
||||
{
|
||||
mz_stream_buffered *buffered = NULL;
|
||||
if (stream == NULL)
|
||||
return;
|
||||
buffered = (mz_stream_buffered *)*stream;
|
||||
if (buffered != NULL)
|
||||
MZ_FREE(buffered);
|
||||
*stream = NULL;
|
||||
}
|
||||
|
||||
void *mz_stream_buffered_get_interface(void)
|
||||
{
|
||||
return (void *)&mz_stream_buffered_vtbl;
|
||||
}
|
43
third-party/ZipArchive/Sources/minizip/mz_strm_buf.h
vendored
Normal file
43
third-party/ZipArchive/Sources/minizip/mz_strm_buf.h
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
/* mz_strm_buf.h -- Stream for buffering reads/writes
|
||||
Version 2.9.2, February 12, 2020
|
||||
part of the MiniZip project
|
||||
|
||||
This version of ioapi is designed to buffer IO.
|
||||
|
||||
Copyright (C) 2010-2020 Nathan Moinvaziri
|
||||
https://github.com/nmoinvaz/minizip
|
||||
|
||||
This program is distributed under the terms of the same license as zlib.
|
||||
See the accompanying LICENSE file for the full text of the license.
|
||||
*/
|
||||
|
||||
#ifndef MZ_STREAM_BUFFERED_H
|
||||
#define MZ_STREAM_BUFFERED_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_stream_buffered_open(void *stream, const char *path, int32_t mode);
|
||||
int32_t mz_stream_buffered_is_open(void *stream);
|
||||
int32_t mz_stream_buffered_read(void *stream, void *buf, int32_t size);
|
||||
int32_t mz_stream_buffered_write(void *stream, const void *buf, int32_t size);
|
||||
int64_t mz_stream_buffered_tell(void *stream);
|
||||
int32_t mz_stream_buffered_seek(void *stream, int64_t offset, int32_t origin);
|
||||
int32_t mz_stream_buffered_close(void *stream);
|
||||
int32_t mz_stream_buffered_error(void *stream);
|
||||
|
||||
void* mz_stream_buffered_create(void **stream);
|
||||
void mz_stream_buffered_delete(void **stream);
|
||||
|
||||
void* mz_stream_buffered_get_interface(void);
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
303
third-party/ZipArchive/Sources/minizip/mz_strm_mem.c
vendored
Normal file
303
third-party/ZipArchive/Sources/minizip/mz_strm_mem.c
vendored
Normal file
@ -0,0 +1,303 @@
|
||||
/* mz_strm_mem.c -- Stream for memory access
|
||||
Version 2.9.2, February 12, 2020
|
||||
part of the MiniZip project
|
||||
|
||||
This interface is designed to access memory rather than files.
|
||||
We do use a region of memory to put data in to and take it out of.
|
||||
|
||||
Based on Unzip ioapi.c version 0.22, May 19th, 2003
|
||||
|
||||
Copyright (C) 2010-2020 Nathan Moinvaziri
|
||||
https://github.com/nmoinvaz/minizip
|
||||
Copyright (C) 2003 Justin Fletcher
|
||||
Copyright (C) 1998-2003 Gilles Vollant
|
||||
https://www.winimage.com/zLibDll/minizip.html
|
||||
|
||||
This program is distributed under the terms of the same license as zlib.
|
||||
See the accompanying LICENSE file for the full text of the license.
|
||||
*/
|
||||
|
||||
|
||||
#include "mz.h"
|
||||
#include "mz_strm.h"
|
||||
#include "mz_strm_mem.h"
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
static mz_stream_vtbl mz_stream_mem_vtbl = {
|
||||
mz_stream_mem_open,
|
||||
mz_stream_mem_is_open,
|
||||
mz_stream_mem_read,
|
||||
mz_stream_mem_write,
|
||||
mz_stream_mem_tell,
|
||||
mz_stream_mem_seek,
|
||||
mz_stream_mem_close,
|
||||
mz_stream_mem_error,
|
||||
mz_stream_mem_create,
|
||||
mz_stream_mem_delete,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
typedef struct mz_stream_mem_s {
|
||||
mz_stream stream;
|
||||
int32_t mode;
|
||||
uint8_t *buffer; /* Memory buffer pointer */
|
||||
int32_t size; /* Size of the memory buffer */
|
||||
int32_t limit; /* Furthest we've written */
|
||||
int32_t position; /* Current position in the memory */
|
||||
int32_t grow_size; /* Size to grow when full */
|
||||
} mz_stream_mem;
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
static int32_t mz_stream_mem_set_size(void *stream, int32_t size)
|
||||
{
|
||||
mz_stream_mem *mem = (mz_stream_mem *)stream;
|
||||
int32_t new_size = size;
|
||||
uint8_t *new_buf = NULL;
|
||||
|
||||
|
||||
new_buf = (uint8_t *)MZ_ALLOC((uint32_t)new_size);
|
||||
if (new_buf == NULL)
|
||||
return MZ_BUF_ERROR;
|
||||
|
||||
if (mem->buffer)
|
||||
{
|
||||
memcpy(new_buf, mem->buffer, mem->size);
|
||||
MZ_FREE(mem->buffer);
|
||||
}
|
||||
|
||||
mem->buffer = new_buf;
|
||||
mem->size = new_size;
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_stream_mem_open(void *stream, const char *path, int32_t mode)
|
||||
{
|
||||
mz_stream_mem *mem = (mz_stream_mem *)stream;
|
||||
int32_t err = MZ_OK;
|
||||
|
||||
MZ_UNUSED(path);
|
||||
|
||||
mem->mode = mode;
|
||||
mem->limit = 0;
|
||||
mem->position = 0;
|
||||
|
||||
if (mem->mode & MZ_OPEN_MODE_CREATE)
|
||||
err = mz_stream_mem_set_size(stream, mem->grow_size);
|
||||
else
|
||||
mem->limit = mem->size;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int32_t mz_stream_mem_is_open(void *stream)
|
||||
{
|
||||
mz_stream_mem *mem = (mz_stream_mem *)stream;
|
||||
if (mem->buffer == NULL)
|
||||
return MZ_OPEN_ERROR;
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_stream_mem_read(void *stream, void *buf, int32_t size)
|
||||
{
|
||||
mz_stream_mem *mem = (mz_stream_mem *)stream;
|
||||
|
||||
if (size > mem->size - mem->position)
|
||||
size = mem->size - mem->position;
|
||||
if (mem->position + size > mem->limit)
|
||||
size = mem->limit - mem->position;
|
||||
|
||||
if (size <= 0)
|
||||
return 0;
|
||||
|
||||
memcpy(buf, mem->buffer + mem->position, size);
|
||||
mem->position += size;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int32_t mz_stream_mem_write(void *stream, const void *buf, int32_t size)
|
||||
{
|
||||
mz_stream_mem *mem = (mz_stream_mem *)stream;
|
||||
int32_t new_size = 0;
|
||||
int32_t err = MZ_OK;
|
||||
|
||||
if (size == 0)
|
||||
return size;
|
||||
|
||||
if (size > mem->size - mem->position)
|
||||
{
|
||||
if (mem->mode & MZ_OPEN_MODE_CREATE)
|
||||
{
|
||||
new_size = mem->size;
|
||||
if (size < mem->grow_size)
|
||||
new_size += mem->grow_size;
|
||||
else
|
||||
new_size += size;
|
||||
|
||||
err = mz_stream_mem_set_size(stream, new_size);
|
||||
if (err != MZ_OK)
|
||||
return err;
|
||||
}
|
||||
else
|
||||
{
|
||||
size = mem->size - mem->position;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(mem->buffer + mem->position, buf, size);
|
||||
|
||||
mem->position += size;
|
||||
if (mem->position > mem->limit)
|
||||
mem->limit = mem->position;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int64_t mz_stream_mem_tell(void *stream)
|
||||
{
|
||||
mz_stream_mem *mem = (mz_stream_mem *)stream;
|
||||
return mem->position;
|
||||
}
|
||||
|
||||
int32_t mz_stream_mem_seek(void *stream, int64_t offset, int32_t origin)
|
||||
{
|
||||
mz_stream_mem *mem = (mz_stream_mem *)stream;
|
||||
int64_t new_pos = 0;
|
||||
int32_t err = MZ_OK;
|
||||
|
||||
switch (origin)
|
||||
{
|
||||
case MZ_SEEK_CUR:
|
||||
new_pos = mem->position + offset;
|
||||
break;
|
||||
case MZ_SEEK_END:
|
||||
new_pos = mem->limit + offset;
|
||||
break;
|
||||
case MZ_SEEK_SET:
|
||||
new_pos = offset;
|
||||
break;
|
||||
default:
|
||||
return MZ_SEEK_ERROR;
|
||||
}
|
||||
|
||||
if (new_pos > mem->size)
|
||||
{
|
||||
if ((mem->mode & MZ_OPEN_MODE_CREATE) == 0)
|
||||
return MZ_SEEK_ERROR;
|
||||
|
||||
err = mz_stream_mem_set_size(stream, (int32_t)new_pos);
|
||||
if (err != MZ_OK)
|
||||
return err;
|
||||
}
|
||||
else if (new_pos < 0)
|
||||
{
|
||||
return MZ_SEEK_ERROR;
|
||||
}
|
||||
|
||||
mem->position = (int32_t)new_pos;
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_stream_mem_close(void *stream)
|
||||
{
|
||||
MZ_UNUSED(stream);
|
||||
|
||||
/* We never return errors */
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_stream_mem_error(void *stream)
|
||||
{
|
||||
MZ_UNUSED(stream);
|
||||
|
||||
/* We never return errors */
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
void mz_stream_mem_set_buffer(void *stream, void *buf, int32_t size)
|
||||
{
|
||||
mz_stream_mem *mem = (mz_stream_mem *)stream;
|
||||
mem->buffer = (uint8_t *)buf;
|
||||
mem->size = size;
|
||||
mem->limit = size;
|
||||
}
|
||||
|
||||
int32_t mz_stream_mem_get_buffer(void *stream, const void **buf)
|
||||
{
|
||||
return mz_stream_mem_get_buffer_at(stream, 0, buf);
|
||||
}
|
||||
|
||||
int32_t mz_stream_mem_get_buffer_at(void *stream, int64_t position, const void **buf)
|
||||
{
|
||||
mz_stream_mem *mem = (mz_stream_mem *)stream;
|
||||
if (buf == NULL || position < 0 || mem->size < position || mem->buffer == NULL)
|
||||
return MZ_SEEK_ERROR;
|
||||
*buf = mem->buffer + position;
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_stream_mem_get_buffer_at_current(void *stream, const void **buf)
|
||||
{
|
||||
mz_stream_mem *mem = (mz_stream_mem *)stream;
|
||||
return mz_stream_mem_get_buffer_at(stream, mem->position, buf);
|
||||
}
|
||||
|
||||
void mz_stream_mem_get_buffer_length(void *stream, int32_t *length)
|
||||
{
|
||||
mz_stream_mem *mem = (mz_stream_mem *)stream;
|
||||
*length = mem->limit;
|
||||
}
|
||||
|
||||
void mz_stream_mem_set_buffer_limit(void *stream, int32_t limit)
|
||||
{
|
||||
mz_stream_mem *mem = (mz_stream_mem *)stream;
|
||||
mem->limit = limit;
|
||||
}
|
||||
|
||||
void mz_stream_mem_set_grow_size(void *stream, int32_t grow_size)
|
||||
{
|
||||
mz_stream_mem *mem = (mz_stream_mem *)stream;
|
||||
mem->grow_size = grow_size;
|
||||
}
|
||||
|
||||
void *mz_stream_mem_create(void **stream)
|
||||
{
|
||||
mz_stream_mem *mem = NULL;
|
||||
|
||||
mem = (mz_stream_mem *)MZ_ALLOC(sizeof(mz_stream_mem));
|
||||
if (mem != NULL)
|
||||
{
|
||||
memset(mem, 0, sizeof(mz_stream_mem));
|
||||
mem->stream.vtbl = &mz_stream_mem_vtbl;
|
||||
mem->grow_size = 4096;
|
||||
}
|
||||
if (stream != NULL)
|
||||
*stream = mem;
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
void mz_stream_mem_delete(void **stream)
|
||||
{
|
||||
mz_stream_mem *mem = NULL;
|
||||
if (stream == NULL)
|
||||
return;
|
||||
mem = (mz_stream_mem *)*stream;
|
||||
if (mem != NULL)
|
||||
{
|
||||
if ((mem->mode & MZ_OPEN_MODE_CREATE) && (mem->buffer != NULL))
|
||||
MZ_FREE(mem->buffer);
|
||||
MZ_FREE(mem);
|
||||
}
|
||||
*stream = NULL;
|
||||
}
|
||||
|
||||
void *mz_stream_mem_get_interface(void)
|
||||
{
|
||||
return (void *)&mz_stream_mem_vtbl;
|
||||
}
|
49
third-party/ZipArchive/Sources/minizip/mz_strm_mem.h
vendored
Normal file
49
third-party/ZipArchive/Sources/minizip/mz_strm_mem.h
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
/* mz_strm_mem.h -- Stream for memory access
|
||||
Version 2.9.2, February 12, 2020
|
||||
part of MiniZip project
|
||||
|
||||
Copyright (C) 2010-2020 Nathan Moinvaziri
|
||||
https://github.com/nmoinvaz/minizip
|
||||
|
||||
This program is distributed under the terms of the same license as zlib.
|
||||
See the accompanying LICENSE file for the full text of the license.
|
||||
*/
|
||||
|
||||
#ifndef MZ_STREAM_MEM_H
|
||||
#define MZ_STREAM_MEM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_stream_mem_open(void *stream, const char *filename, int32_t mode);
|
||||
int32_t mz_stream_mem_is_open(void *stream);
|
||||
int32_t mz_stream_mem_read(void *stream, void *buf, int32_t size);
|
||||
int32_t mz_stream_mem_write(void *stream, const void *buf, int32_t size);
|
||||
int64_t mz_stream_mem_tell(void *stream);
|
||||
int32_t mz_stream_mem_seek(void *stream, int64_t offset, int32_t origin);
|
||||
int32_t mz_stream_mem_close(void *stream);
|
||||
int32_t mz_stream_mem_error(void *stream);
|
||||
|
||||
void mz_stream_mem_set_buffer(void *stream, void *buf, int32_t size);
|
||||
int32_t mz_stream_mem_get_buffer(void *stream, const void **buf);
|
||||
int32_t mz_stream_mem_get_buffer_at(void *stream, int64_t position, const void **buf);
|
||||
int32_t mz_stream_mem_get_buffer_at_current(void *stream, const void **buf);
|
||||
void mz_stream_mem_get_buffer_length(void *stream, int32_t *length);
|
||||
void mz_stream_mem_set_buffer_limit(void *stream, int32_t limit);
|
||||
void mz_stream_mem_set_grow_size(void *stream, int32_t grow_size);
|
||||
|
||||
void* mz_stream_mem_create(void **stream);
|
||||
void mz_stream_mem_delete(void **stream);
|
||||
|
||||
void* mz_stream_mem_get_interface(void);
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
41
third-party/ZipArchive/Sources/minizip/mz_strm_os.h
vendored
Normal file
41
third-party/ZipArchive/Sources/minizip/mz_strm_os.h
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
/* mz_sstrm_os.h -- Stream for filesystem access
|
||||
Version 2.9.2, February 12, 2020
|
||||
part of the MiniZip project
|
||||
|
||||
Copyright (C) 2010-2020 Nathan Moinvaziri
|
||||
https://github.com/nmoinvaz/minizip
|
||||
|
||||
This program is distributed under the terms of the same license as zlib.
|
||||
See the accompanying LICENSE file for the full text of the license.
|
||||
*/
|
||||
|
||||
#ifndef MZ_STREAM_OS_H
|
||||
#define MZ_STREAM_OS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_stream_os_open(void *stream, const char *path, int32_t mode);
|
||||
int32_t mz_stream_os_is_open(void *stream);
|
||||
int32_t mz_stream_os_read(void *stream, void *buf, int32_t size);
|
||||
int32_t mz_stream_os_write(void *stream, const void *buf, int32_t size);
|
||||
int64_t mz_stream_os_tell(void *stream);
|
||||
int32_t mz_stream_os_seek(void *stream, int64_t offset, int32_t origin);
|
||||
int32_t mz_stream_os_close(void *stream);
|
||||
int32_t mz_stream_os_error(void *stream);
|
||||
|
||||
void* mz_stream_os_create(void **stream);
|
||||
void mz_stream_os_delete(void **stream);
|
||||
|
||||
void* mz_stream_os_get_interface(void);
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
228
third-party/ZipArchive/Sources/minizip/mz_strm_os_posix.c
vendored
Normal file
228
third-party/ZipArchive/Sources/minizip/mz_strm_os_posix.c
vendored
Normal file
@ -0,0 +1,228 @@
|
||||
/* mz_strm_posix.c -- Stream for filesystem access for posix/linux
|
||||
Version 2.9.2, February 12, 2020
|
||||
part of the MiniZip project
|
||||
|
||||
Copyright (C) 2010-2020 Nathan Moinvaziri
|
||||
https://github.com/nmoinvaz/minizip
|
||||
Modifications for Zip64 support
|
||||
Copyright (C) 2009-2010 Mathias Svensson
|
||||
http://result42.com
|
||||
Copyright (C) 1998-2010 Gilles Vollant
|
||||
https://www.winimage.com/zLibDll/minizip.html
|
||||
|
||||
This program is distributed under the terms of the same license as zlib.
|
||||
See the accompanying LICENSE file for the full text of the license.
|
||||
*/
|
||||
|
||||
|
||||
#include "mz.h"
|
||||
#include "mz_strm.h"
|
||||
#include "mz_strm_os.h"
|
||||
|
||||
#include <stdio.h> /* fopen, fread.. */
|
||||
#include <errno.h>
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#define fopen64 fopen
|
||||
#ifndef MZ_FILE32_API
|
||||
# ifndef NO_FSEEKO
|
||||
# define ftello64 ftello
|
||||
# define fseeko64 fseeko
|
||||
# elif defined(_MSC_VER) && (_MSC_VER >= 1400)
|
||||
# define ftello64 _ftelli64
|
||||
# define fseeko64 _fseeki64
|
||||
# endif
|
||||
#endif
|
||||
#ifndef ftello64
|
||||
# define ftello64 ftell
|
||||
#endif
|
||||
#ifndef fseeko64
|
||||
# define fseeko64 fseek
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
static mz_stream_vtbl mz_stream_os_vtbl = {
|
||||
mz_stream_os_open,
|
||||
mz_stream_os_is_open,
|
||||
mz_stream_os_read,
|
||||
mz_stream_os_write,
|
||||
mz_stream_os_tell,
|
||||
mz_stream_os_seek,
|
||||
mz_stream_os_close,
|
||||
mz_stream_os_error,
|
||||
mz_stream_os_create,
|
||||
mz_stream_os_delete,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
typedef struct mz_stream_posix_s
|
||||
{
|
||||
mz_stream stream;
|
||||
int32_t error;
|
||||
FILE *handle;
|
||||
} mz_stream_posix;
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_stream_os_open(void *stream, const char *path, int32_t mode)
|
||||
{
|
||||
mz_stream_posix *posix = (mz_stream_posix *)stream;
|
||||
const char *mode_fopen = NULL;
|
||||
|
||||
if (path == NULL)
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
if ((mode & MZ_OPEN_MODE_READWRITE) == MZ_OPEN_MODE_READ)
|
||||
mode_fopen = "rb";
|
||||
else if (mode & MZ_OPEN_MODE_APPEND)
|
||||
mode_fopen = "r+b";
|
||||
else if (mode & MZ_OPEN_MODE_CREATE)
|
||||
mode_fopen = "wb";
|
||||
else
|
||||
return MZ_OPEN_ERROR;
|
||||
|
||||
posix->handle = fopen64(path, mode_fopen);
|
||||
if (posix->handle == NULL)
|
||||
{
|
||||
posix->error = errno;
|
||||
return MZ_OPEN_ERROR;
|
||||
}
|
||||
|
||||
if (mode & MZ_OPEN_MODE_APPEND)
|
||||
return mz_stream_os_seek(stream, 0, MZ_SEEK_END);
|
||||
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_stream_os_is_open(void *stream)
|
||||
{
|
||||
mz_stream_posix *posix = (mz_stream_posix*)stream;
|
||||
if (posix->handle == NULL)
|
||||
return MZ_OPEN_ERROR;
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_stream_os_read(void *stream, void *buf, int32_t size)
|
||||
{
|
||||
mz_stream_posix *posix = (mz_stream_posix*)stream;
|
||||
int32_t read = (int32_t)fread(buf, 1, (size_t)size, posix->handle);
|
||||
if (read < size && ferror(posix->handle))
|
||||
{
|
||||
posix->error = errno;
|
||||
return MZ_READ_ERROR;
|
||||
}
|
||||
return read;
|
||||
}
|
||||
|
||||
int32_t mz_stream_os_write(void *stream, const void *buf, int32_t size)
|
||||
{
|
||||
mz_stream_posix *posix = (mz_stream_posix*)stream;
|
||||
int32_t written = (int32_t)fwrite(buf, 1, (size_t)size, posix->handle);
|
||||
if (written < size && ferror(posix->handle))
|
||||
{
|
||||
posix->error = errno;
|
||||
return MZ_WRITE_ERROR;
|
||||
}
|
||||
return written;
|
||||
}
|
||||
|
||||
int64_t mz_stream_os_tell(void *stream)
|
||||
{
|
||||
mz_stream_posix *posix = (mz_stream_posix*)stream;
|
||||
int64_t position = ftello64(posix->handle);
|
||||
if (position == -1)
|
||||
{
|
||||
posix->error = errno;
|
||||
return MZ_TELL_ERROR;
|
||||
}
|
||||
return position;
|
||||
}
|
||||
|
||||
int32_t mz_stream_os_seek(void *stream, int64_t offset, int32_t origin)
|
||||
{
|
||||
mz_stream_posix *posix = (mz_stream_posix*)stream;
|
||||
int32_t fseek_origin = 0;
|
||||
|
||||
switch (origin)
|
||||
{
|
||||
case MZ_SEEK_CUR:
|
||||
fseek_origin = SEEK_CUR;
|
||||
break;
|
||||
case MZ_SEEK_END:
|
||||
fseek_origin = SEEK_END;
|
||||
break;
|
||||
case MZ_SEEK_SET:
|
||||
fseek_origin = SEEK_SET;
|
||||
break;
|
||||
default:
|
||||
return MZ_SEEK_ERROR;
|
||||
}
|
||||
|
||||
if (fseeko64(posix->handle, offset, fseek_origin) != 0)
|
||||
{
|
||||
posix->error = errno;
|
||||
return MZ_SEEK_ERROR;
|
||||
}
|
||||
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_stream_os_close(void *stream)
|
||||
{
|
||||
mz_stream_posix *posix = (mz_stream_posix*)stream;
|
||||
int32_t closed = 0;
|
||||
if (posix->handle != NULL)
|
||||
{
|
||||
closed = fclose(posix->handle);
|
||||
posix->handle = NULL;
|
||||
}
|
||||
if (closed != 0)
|
||||
{
|
||||
posix->error = errno;
|
||||
return MZ_CLOSE_ERROR;
|
||||
}
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_stream_os_error(void *stream)
|
||||
{
|
||||
mz_stream_posix *posix = (mz_stream_posix*)stream;
|
||||
return posix->error;
|
||||
}
|
||||
|
||||
void *mz_stream_os_create(void **stream)
|
||||
{
|
||||
mz_stream_posix *posix = NULL;
|
||||
|
||||
posix = (mz_stream_posix *)MZ_ALLOC(sizeof(mz_stream_posix));
|
||||
if (posix != NULL)
|
||||
{
|
||||
memset(posix, 0, sizeof(mz_stream_posix));
|
||||
posix->stream.vtbl = &mz_stream_os_vtbl;
|
||||
}
|
||||
if (stream != NULL)
|
||||
*stream = posix;
|
||||
|
||||
return posix;
|
||||
}
|
||||
|
||||
void mz_stream_os_delete(void **stream)
|
||||
{
|
||||
mz_stream_posix *posix = NULL;
|
||||
if (stream == NULL)
|
||||
return;
|
||||
posix = (mz_stream_posix *)*stream;
|
||||
if (posix != NULL)
|
||||
MZ_FREE(posix);
|
||||
*stream = NULL;
|
||||
}
|
||||
|
||||
void *mz_stream_os_get_interface(void)
|
||||
{
|
||||
return (void *)&mz_stream_os_vtbl;
|
||||
}
|
384
third-party/ZipArchive/Sources/minizip/mz_strm_pkcrypt.c
vendored
Normal file
384
third-party/ZipArchive/Sources/minizip/mz_strm_pkcrypt.c
vendored
Normal file
@ -0,0 +1,384 @@
|
||||
/* mz_strm_pkcrypt.c -- Code for traditional PKWARE encryption
|
||||
Version 2.9.2, February 12, 2020
|
||||
part of the MiniZip project
|
||||
|
||||
Copyright (C) 2010-2020 Nathan Moinvaziri
|
||||
https://github.com/nmoinvaz/minizip
|
||||
Copyright (C) 1998-2005 Gilles Vollant
|
||||
Modifications for Info-ZIP crypting
|
||||
https://www.winimage.com/zLibDll/minizip.html
|
||||
Copyright (C) 2003 Terry Thorsen
|
||||
|
||||
This code is a modified version of crypting code in Info-ZIP distribution
|
||||
|
||||
Copyright (C) 1990-2000 Info-ZIP. All rights reserved.
|
||||
|
||||
This program is distributed under the terms of the same license as zlib.
|
||||
See the accompanying LICENSE file for the full text of the license.
|
||||
|
||||
This encryption code is a direct transcription of the algorithm from
|
||||
Roger Schlafly, described by Phil Katz in the file appnote.txt. This
|
||||
file (appnote.txt) is distributed with the PKZIP program (even in the
|
||||
version without encryption capabilities).
|
||||
*/
|
||||
|
||||
|
||||
#include "mz.h"
|
||||
#include "mz_crypt.h"
|
||||
#include "mz_strm.h"
|
||||
#include "mz_strm_pkcrypt.h"
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
static mz_stream_vtbl mz_stream_pkcrypt_vtbl = {
|
||||
mz_stream_pkcrypt_open,
|
||||
mz_stream_pkcrypt_is_open,
|
||||
mz_stream_pkcrypt_read,
|
||||
mz_stream_pkcrypt_write,
|
||||
mz_stream_pkcrypt_tell,
|
||||
mz_stream_pkcrypt_seek,
|
||||
mz_stream_pkcrypt_close,
|
||||
mz_stream_pkcrypt_error,
|
||||
mz_stream_pkcrypt_create,
|
||||
mz_stream_pkcrypt_delete,
|
||||
mz_stream_pkcrypt_get_prop_int64,
|
||||
mz_stream_pkcrypt_set_prop_int64
|
||||
};
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
typedef struct mz_stream_pkcrypt_s {
|
||||
mz_stream stream;
|
||||
int32_t error;
|
||||
int16_t initialized;
|
||||
uint8_t buffer[UINT16_MAX];
|
||||
int64_t total_in;
|
||||
int64_t max_total_in;
|
||||
int64_t total_out;
|
||||
uint32_t keys[3]; /* keys defining the pseudo-random sequence */
|
||||
uint8_t verify1;
|
||||
uint8_t verify2;
|
||||
const char *password;
|
||||
} mz_stream_pkcrypt;
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#define mz_stream_pkcrypt_decode(strm, c) \
|
||||
(mz_stream_pkcrypt_update_keys(strm, \
|
||||
c ^= mz_stream_pkcrypt_decrypt_byte(strm)))
|
||||
|
||||
#define mz_stream_pkcrypt_encode(strm, c, t) \
|
||||
(t = mz_stream_pkcrypt_decrypt_byte(strm), \
|
||||
mz_stream_pkcrypt_update_keys(strm, (uint8_t)c), (uint8_t)(t^(c)))
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
static uint8_t mz_stream_pkcrypt_decrypt_byte(void *stream)
|
||||
{
|
||||
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
|
||||
|
||||
unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an */
|
||||
/* unpredictable manner on 16-bit systems; not a problem */
|
||||
/* with any known compiler so far, though. */
|
||||
|
||||
temp = pkcrypt->keys[2] | 2;
|
||||
return (uint8_t)(((temp * (temp ^ 1)) >> 8) & 0xff);
|
||||
}
|
||||
|
||||
static uint8_t mz_stream_pkcrypt_update_keys(void *stream, uint8_t c)
|
||||
{
|
||||
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
|
||||
uint8_t buf = c;
|
||||
|
||||
pkcrypt->keys[0] = (uint32_t)~mz_crypt_crc32_update(~pkcrypt->keys[0], &buf, 1);
|
||||
|
||||
pkcrypt->keys[1] += pkcrypt->keys[0] & 0xff;
|
||||
pkcrypt->keys[1] *= 134775813L;
|
||||
pkcrypt->keys[1] += 1;
|
||||
|
||||
buf = (uint8_t)(pkcrypt->keys[1] >> 24);
|
||||
pkcrypt->keys[2] = (uint32_t)~mz_crypt_crc32_update(~pkcrypt->keys[2], &buf, 1);
|
||||
|
||||
return (uint8_t)c;
|
||||
}
|
||||
|
||||
static void mz_stream_pkcrypt_init_keys(void *stream, const char *password)
|
||||
{
|
||||
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
|
||||
|
||||
pkcrypt->keys[0] = 305419896L;
|
||||
pkcrypt->keys[1] = 591751049L;
|
||||
pkcrypt->keys[2] = 878082192L;
|
||||
|
||||
while (*password != 0)
|
||||
{
|
||||
mz_stream_pkcrypt_update_keys(stream, (uint8_t)*password);
|
||||
password += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_stream_pkcrypt_open(void *stream, const char *path, int32_t mode)
|
||||
{
|
||||
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
|
||||
uint16_t t = 0;
|
||||
int16_t i = 0;
|
||||
uint8_t verify1 = 0;
|
||||
uint8_t verify2 = 0;
|
||||
uint8_t header[MZ_PKCRYPT_HEADER_SIZE];
|
||||
const char *password = path;
|
||||
|
||||
pkcrypt->total_in = 0;
|
||||
pkcrypt->total_out = 0;
|
||||
pkcrypt->initialized = 0;
|
||||
|
||||
if (mz_stream_is_open(pkcrypt->stream.base) != MZ_OK)
|
||||
return MZ_OPEN_ERROR;
|
||||
|
||||
if (password == NULL)
|
||||
password = pkcrypt->password;
|
||||
if (password == NULL)
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
mz_stream_pkcrypt_init_keys(stream, password);
|
||||
|
||||
if (mode & MZ_OPEN_MODE_WRITE)
|
||||
{
|
||||
#ifdef MZ_ZIP_NO_COMPRESSION
|
||||
MZ_UNUSED(t);
|
||||
MZ_UNUSED(i);
|
||||
|
||||
return MZ_SUPPORT_ERROR;
|
||||
#else
|
||||
/* First generate RAND_HEAD_LEN - 2 random bytes. */
|
||||
mz_crypt_rand(header, MZ_PKCRYPT_HEADER_SIZE - 2);
|
||||
|
||||
/* Encrypt random header (last two bytes is high word of crc) */
|
||||
for (i = 0; i < MZ_PKCRYPT_HEADER_SIZE - 2; i++)
|
||||
header[i] = mz_stream_pkcrypt_encode(stream, header[i], t);
|
||||
|
||||
header[i++] = mz_stream_pkcrypt_encode(stream, pkcrypt->verify1, t);
|
||||
header[i++] = mz_stream_pkcrypt_encode(stream, pkcrypt->verify2, t);
|
||||
|
||||
if (mz_stream_write(pkcrypt->stream.base, header, sizeof(header)) != sizeof(header))
|
||||
return MZ_WRITE_ERROR;
|
||||
|
||||
pkcrypt->total_out += MZ_PKCRYPT_HEADER_SIZE;
|
||||
#endif
|
||||
}
|
||||
else if (mode & MZ_OPEN_MODE_READ)
|
||||
{
|
||||
#ifdef MZ_ZIP_NO_DECOMPRESSION
|
||||
MZ_UNUSED(t);
|
||||
MZ_UNUSED(i);
|
||||
MZ_UNUSED(verify1);
|
||||
MZ_UNUSED(verify2);
|
||||
|
||||
return MZ_SUPPORT_ERROR;
|
||||
#else
|
||||
if (mz_stream_read(pkcrypt->stream.base, header, sizeof(header)) != sizeof(header))
|
||||
return MZ_READ_ERROR;
|
||||
|
||||
for (i = 0; i < MZ_PKCRYPT_HEADER_SIZE - 2; i++)
|
||||
header[i] = mz_stream_pkcrypt_decode(stream, header[i]);
|
||||
|
||||
verify1 = mz_stream_pkcrypt_decode(stream, header[i++]);
|
||||
verify2 = mz_stream_pkcrypt_decode(stream, header[i++]);
|
||||
|
||||
/* Older versions used 2 byte check, newer versions use 1 byte check. */
|
||||
MZ_UNUSED(verify1);
|
||||
if ((verify2 != 0) && (verify2 != pkcrypt->verify2))
|
||||
return MZ_PASSWORD_ERROR;
|
||||
|
||||
pkcrypt->total_in += MZ_PKCRYPT_HEADER_SIZE;
|
||||
#endif
|
||||
}
|
||||
|
||||
pkcrypt->initialized = 1;
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_stream_pkcrypt_is_open(void *stream)
|
||||
{
|
||||
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
|
||||
if (pkcrypt->initialized == 0)
|
||||
return MZ_OPEN_ERROR;
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_stream_pkcrypt_read(void *stream, void *buf, int32_t size)
|
||||
{
|
||||
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
|
||||
uint8_t *buf_ptr = (uint8_t *)buf;
|
||||
int32_t bytes_to_read = size;
|
||||
int32_t read = 0;
|
||||
int32_t i = 0;
|
||||
|
||||
|
||||
if ((int64_t)bytes_to_read > (pkcrypt->max_total_in - pkcrypt->total_in))
|
||||
bytes_to_read = (int32_t)(pkcrypt->max_total_in - pkcrypt->total_in);
|
||||
|
||||
read = mz_stream_read(pkcrypt->stream.base, buf, bytes_to_read);
|
||||
|
||||
for (i = 0; i < read; i++)
|
||||
buf_ptr[i] = mz_stream_pkcrypt_decode(stream, buf_ptr[i]);
|
||||
|
||||
if (read > 0)
|
||||
pkcrypt->total_in += read;
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
int32_t mz_stream_pkcrypt_write(void *stream, const void *buf, int32_t size)
|
||||
{
|
||||
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
|
||||
const uint8_t *buf_ptr = (const uint8_t *)buf;
|
||||
int32_t bytes_to_write = sizeof(pkcrypt->buffer);
|
||||
int32_t total_written = 0;
|
||||
int32_t written = 0;
|
||||
int32_t i = 0;
|
||||
uint16_t t = 0;
|
||||
|
||||
if (size < 0)
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
do
|
||||
{
|
||||
if (bytes_to_write > (size - total_written))
|
||||
bytes_to_write = (size - total_written);
|
||||
|
||||
for (i = 0; i < bytes_to_write; i += 1)
|
||||
{
|
||||
pkcrypt->buffer[i] = mz_stream_pkcrypt_encode(stream, *buf_ptr, t);
|
||||
buf_ptr += 1;
|
||||
}
|
||||
|
||||
written = mz_stream_write(pkcrypt->stream.base, pkcrypt->buffer, bytes_to_write);
|
||||
if (written < 0)
|
||||
return written;
|
||||
|
||||
total_written += written;
|
||||
}
|
||||
while (total_written < size && written > 0);
|
||||
|
||||
pkcrypt->total_out += total_written;
|
||||
return total_written;
|
||||
}
|
||||
|
||||
int64_t mz_stream_pkcrypt_tell(void *stream)
|
||||
{
|
||||
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
|
||||
return mz_stream_tell(pkcrypt->stream.base);
|
||||
}
|
||||
|
||||
int32_t mz_stream_pkcrypt_seek(void *stream, int64_t offset, int32_t origin)
|
||||
{
|
||||
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
|
||||
return mz_stream_seek(pkcrypt->stream.base, offset, origin);
|
||||
}
|
||||
|
||||
int32_t mz_stream_pkcrypt_close(void *stream)
|
||||
{
|
||||
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
|
||||
pkcrypt->initialized = 0;
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_stream_pkcrypt_error(void *stream)
|
||||
{
|
||||
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
|
||||
return pkcrypt->error;
|
||||
}
|
||||
|
||||
void mz_stream_pkcrypt_set_password(void *stream, const char *password)
|
||||
{
|
||||
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
|
||||
pkcrypt->password = password;
|
||||
}
|
||||
|
||||
void mz_stream_pkcrypt_set_verify(void *stream, uint8_t verify1, uint8_t verify2)
|
||||
{
|
||||
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
|
||||
pkcrypt->verify1 = verify1;
|
||||
pkcrypt->verify2 = verify2;
|
||||
}
|
||||
|
||||
void mz_stream_pkcrypt_get_verify(void *stream, uint8_t *verify1, uint8_t *verify2)
|
||||
{
|
||||
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
|
||||
*verify1 = pkcrypt->verify1;
|
||||
*verify2 = pkcrypt->verify2;
|
||||
}
|
||||
|
||||
int32_t mz_stream_pkcrypt_get_prop_int64(void *stream, int32_t prop, int64_t *value)
|
||||
{
|
||||
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
|
||||
switch (prop)
|
||||
{
|
||||
case MZ_STREAM_PROP_TOTAL_IN:
|
||||
*value = pkcrypt->total_in;
|
||||
break;
|
||||
case MZ_STREAM_PROP_TOTAL_OUT:
|
||||
*value = pkcrypt->total_out;
|
||||
break;
|
||||
case MZ_STREAM_PROP_TOTAL_IN_MAX:
|
||||
*value = pkcrypt->max_total_in;
|
||||
break;
|
||||
case MZ_STREAM_PROP_HEADER_SIZE:
|
||||
*value = MZ_PKCRYPT_HEADER_SIZE;
|
||||
break;
|
||||
case MZ_STREAM_PROP_FOOTER_SIZE:
|
||||
*value = 0;
|
||||
break;
|
||||
default:
|
||||
return MZ_EXIST_ERROR;
|
||||
}
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_stream_pkcrypt_set_prop_int64(void *stream, int32_t prop, int64_t value)
|
||||
{
|
||||
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
|
||||
switch (prop)
|
||||
{
|
||||
case MZ_STREAM_PROP_TOTAL_IN_MAX:
|
||||
pkcrypt->max_total_in = value;
|
||||
break;
|
||||
default:
|
||||
return MZ_EXIST_ERROR;
|
||||
}
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
void *mz_stream_pkcrypt_create(void **stream)
|
||||
{
|
||||
mz_stream_pkcrypt *pkcrypt = NULL;
|
||||
|
||||
pkcrypt = (mz_stream_pkcrypt *)MZ_ALLOC(sizeof(mz_stream_pkcrypt));
|
||||
if (pkcrypt != NULL)
|
||||
{
|
||||
memset(pkcrypt, 0, sizeof(mz_stream_pkcrypt));
|
||||
pkcrypt->stream.vtbl = &mz_stream_pkcrypt_vtbl;
|
||||
}
|
||||
|
||||
if (stream != NULL)
|
||||
*stream = pkcrypt;
|
||||
return pkcrypt;
|
||||
}
|
||||
|
||||
void mz_stream_pkcrypt_delete(void **stream)
|
||||
{
|
||||
mz_stream_pkcrypt *pkcrypt = NULL;
|
||||
if (stream == NULL)
|
||||
return;
|
||||
pkcrypt = (mz_stream_pkcrypt *)*stream;
|
||||
if (pkcrypt != NULL)
|
||||
MZ_FREE(pkcrypt);
|
||||
*stream = NULL;
|
||||
}
|
||||
|
||||
void *mz_stream_pkcrypt_get_interface(void)
|
||||
{
|
||||
return (void *)&mz_stream_pkcrypt_vtbl;
|
||||
}
|
47
third-party/ZipArchive/Sources/minizip/mz_strm_pkcrypt.h
vendored
Normal file
47
third-party/ZipArchive/Sources/minizip/mz_strm_pkcrypt.h
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
/* mz_strm_pkcrypt.h -- Code for traditional PKWARE encryption
|
||||
Version 2.9.2, February 12, 2020
|
||||
part of the MiniZip project
|
||||
|
||||
Copyright (C) 2010-2020 Nathan Moinvaziri
|
||||
https://github.com/nmoinvaz/minizip
|
||||
|
||||
This program is distributed under the terms of the same license as zlib.
|
||||
See the accompanying LICENSE file for the full text of the license.
|
||||
*/
|
||||
|
||||
#ifndef MZ_STREAM_PKCRYPT_H
|
||||
#define MZ_STREAM_PKCRYPT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_stream_pkcrypt_open(void *stream, const char *filename, int32_t mode);
|
||||
int32_t mz_stream_pkcrypt_is_open(void *stream);
|
||||
int32_t mz_stream_pkcrypt_read(void *stream, void *buf, int32_t size);
|
||||
int32_t mz_stream_pkcrypt_write(void *stream, const void *buf, int32_t size);
|
||||
int64_t mz_stream_pkcrypt_tell(void *stream);
|
||||
int32_t mz_stream_pkcrypt_seek(void *stream, int64_t offset, int32_t origin);
|
||||
int32_t mz_stream_pkcrypt_close(void *stream);
|
||||
int32_t mz_stream_pkcrypt_error(void *stream);
|
||||
|
||||
void mz_stream_pkcrypt_set_password(void *stream, const char *password);
|
||||
void mz_stream_pkcrypt_set_verify(void *stream, uint8_t verify1, uint8_t verify2);
|
||||
void mz_stream_pkcrypt_get_verify(void *stream, uint8_t *verify1, uint8_t *verify2);
|
||||
int32_t mz_stream_pkcrypt_get_prop_int64(void *stream, int32_t prop, int64_t *value);
|
||||
int32_t mz_stream_pkcrypt_set_prop_int64(void *stream, int32_t prop, int64_t value);
|
||||
|
||||
void* mz_stream_pkcrypt_create(void **stream);
|
||||
void mz_stream_pkcrypt_delete(void **stream);
|
||||
|
||||
void* mz_stream_pkcrypt_get_interface(void);
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
489
third-party/ZipArchive/Sources/minizip/mz_strm_split.c
vendored
Normal file
489
third-party/ZipArchive/Sources/minizip/mz_strm_split.c
vendored
Normal file
@ -0,0 +1,489 @@
|
||||
/* mz_strm_split.c -- Stream for split files
|
||||
Version 2.9.2, February 12, 2020
|
||||
part of the MiniZip project
|
||||
|
||||
Copyright (C) 2010-2020 Nathan Moinvaziri
|
||||
https://github.com/nmoinvaz/minizip
|
||||
|
||||
This program is distributed under the terms of the same license as zlib.
|
||||
See the accompanying LICENSE file for the full text of the license.
|
||||
*/
|
||||
|
||||
|
||||
#include "mz.h"
|
||||
#include "mz_os.h"
|
||||
#include "mz_strm.h"
|
||||
#include "mz_strm_split.h"
|
||||
|
||||
#include <stdio.h> /* snprintf */
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1900)
|
||||
# define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#define MZ_ZIP_MAGIC_DISKHEADER (0x08074b50)
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
static mz_stream_vtbl mz_stream_split_vtbl = {
|
||||
mz_stream_split_open,
|
||||
mz_stream_split_is_open,
|
||||
mz_stream_split_read,
|
||||
mz_stream_split_write,
|
||||
mz_stream_split_tell,
|
||||
mz_stream_split_seek,
|
||||
mz_stream_split_close,
|
||||
mz_stream_split_error,
|
||||
mz_stream_split_create,
|
||||
mz_stream_split_delete,
|
||||
mz_stream_split_get_prop_int64,
|
||||
mz_stream_split_set_prop_int64
|
||||
};
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
typedef struct mz_stream_split_s {
|
||||
mz_stream stream;
|
||||
int32_t is_open;
|
||||
int64_t disk_size;
|
||||
int64_t total_in;
|
||||
int64_t total_in_disk;
|
||||
int64_t total_out;
|
||||
int64_t total_out_disk;
|
||||
int32_t mode;
|
||||
char *path_cd;
|
||||
uint32_t path_cd_size;
|
||||
char *path_disk;
|
||||
uint32_t path_disk_size;
|
||||
int32_t number_disk;
|
||||
int32_t current_disk;
|
||||
int64_t current_disk_size;
|
||||
int32_t reached_end;
|
||||
} mz_stream_split;
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#if 0
|
||||
# define mz_stream_split_print printf
|
||||
#else
|
||||
# define mz_stream_split_print(fmt,...)
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
static int32_t mz_stream_split_open_disk(void *stream, int32_t number_disk)
|
||||
{
|
||||
mz_stream_split *split = (mz_stream_split *)stream;
|
||||
uint32_t magic = 0;
|
||||
int64_t position = 0;
|
||||
int32_t i = 0;
|
||||
int32_t err = MZ_OK;
|
||||
int16_t disk_part = 0;
|
||||
|
||||
|
||||
/* Check if we are reading or writing a disk part or the cd disk */
|
||||
if (number_disk >= 0)
|
||||
{
|
||||
if ((split->mode & MZ_OPEN_MODE_WRITE) == 0)
|
||||
disk_part = MZ_OPEN_MODE_READ;
|
||||
else if (split->disk_size > 0)
|
||||
disk_part = MZ_OPEN_MODE_WRITE;
|
||||
}
|
||||
|
||||
/* Construct disk path */
|
||||
if (disk_part > 0)
|
||||
{
|
||||
for (i = (int32_t)strlen(split->path_disk) - 1; i >= 0; i -= 1)
|
||||
{
|
||||
if (split->path_disk[i] != '.')
|
||||
continue;
|
||||
snprintf(&split->path_disk[i], split->path_disk_size - (uint32_t)i,
|
||||
".z%02" PRId32, number_disk + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy(split->path_disk, split->path_cd, split->path_disk_size - 1);
|
||||
split->path_disk[split->path_disk_size - 1] = 0;
|
||||
}
|
||||
|
||||
mz_stream_split_print("Split - Goto disk - %s (disk %" PRId32 ")\n", split->path_disk, number_disk);
|
||||
|
||||
/* If disk part doesn't exist during reading then return MZ_EXIST_ERROR */
|
||||
if (disk_part == MZ_OPEN_MODE_READ)
|
||||
err = mz_os_file_exists(split->path_disk);
|
||||
|
||||
if (err == MZ_OK)
|
||||
err = mz_stream_open(split->stream.base, split->path_disk, split->mode);
|
||||
|
||||
if (err == MZ_OK)
|
||||
{
|
||||
split->total_in_disk = 0;
|
||||
split->total_out_disk = 0;
|
||||
split->current_disk = number_disk;
|
||||
|
||||
if (split->mode & MZ_OPEN_MODE_WRITE)
|
||||
{
|
||||
if ((split->current_disk == 0) && (split->disk_size > 0))
|
||||
{
|
||||
err = mz_stream_write_uint32(split->stream.base, MZ_ZIP_MAGIC_DISKHEADER);
|
||||
|
||||
split->total_out_disk += 4;
|
||||
split->total_out += split->total_out_disk;
|
||||
}
|
||||
}
|
||||
else if (split->mode & MZ_OPEN_MODE_READ)
|
||||
{
|
||||
if (split->current_disk == 0)
|
||||
{
|
||||
err = mz_stream_read_uint32(split->stream.base, &magic);
|
||||
if (magic != MZ_ZIP_MAGIC_DISKHEADER)
|
||||
err = MZ_FORMAT_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (err == MZ_OK)
|
||||
{
|
||||
/* Get the size of the current disk we are on */
|
||||
position = mz_stream_tell(split->stream.base);
|
||||
mz_stream_seek(split->stream.base, 0, MZ_SEEK_END);
|
||||
split->current_disk_size = mz_stream_tell(split->stream.base);
|
||||
mz_stream_seek(split->stream.base, position, MZ_SEEK_SET);
|
||||
|
||||
split->is_open = 1;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int32_t mz_stream_split_close_disk(void *stream)
|
||||
{
|
||||
mz_stream_split *split = (mz_stream_split *)stream;
|
||||
|
||||
if (mz_stream_is_open(split->stream.base) != MZ_OK)
|
||||
return MZ_OK;
|
||||
|
||||
mz_stream_split_print("Split - Close disk\n");
|
||||
return mz_stream_close(split->stream.base);
|
||||
}
|
||||
|
||||
static int32_t mz_stream_split_goto_disk(void *stream, int32_t number_disk)
|
||||
{
|
||||
mz_stream_split *split = (mz_stream_split *)stream;
|
||||
int32_t err = MZ_OK;
|
||||
int32_t err_is_open = MZ_OK;
|
||||
|
||||
err_is_open = mz_stream_is_open(split->stream.base);
|
||||
|
||||
if ((split->disk_size == 0) && (split->mode & MZ_OPEN_MODE_WRITE))
|
||||
{
|
||||
if (err_is_open != MZ_OK)
|
||||
err = mz_stream_split_open_disk(stream, number_disk);
|
||||
}
|
||||
else if ((number_disk != split->current_disk) || (err_is_open != MZ_OK))
|
||||
{
|
||||
err = mz_stream_split_close_disk(stream);
|
||||
if (err == MZ_OK)
|
||||
{
|
||||
err = mz_stream_split_open_disk(stream, number_disk);
|
||||
if (err == MZ_OK)
|
||||
split->number_disk = number_disk;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int32_t mz_stream_split_open(void *stream, const char *path, int32_t mode)
|
||||
{
|
||||
mz_stream_split *split = (mz_stream_split *)stream;
|
||||
int32_t number_disk = 0;
|
||||
|
||||
split->mode = mode;
|
||||
|
||||
split->path_cd_size = (uint32_t)strlen(path) + 1;
|
||||
split->path_cd = (char *)MZ_ALLOC(split->path_cd_size);
|
||||
|
||||
if (split->path_cd == NULL)
|
||||
return MZ_MEM_ERROR;
|
||||
|
||||
strncpy(split->path_cd, path, split->path_cd_size - 1);
|
||||
split->path_cd[split->path_cd_size - 1] = 0;
|
||||
|
||||
mz_stream_split_print("Split - Open - %s (disk %" PRId32 ")\n", split->path_cd, number_disk);
|
||||
|
||||
split->path_disk_size = (uint32_t)strlen(path) + 10;
|
||||
split->path_disk = (char *)MZ_ALLOC(split->path_disk_size);
|
||||
|
||||
if (split->path_disk == NULL)
|
||||
{
|
||||
MZ_FREE(split->path_cd);
|
||||
return MZ_MEM_ERROR;
|
||||
}
|
||||
|
||||
strncpy(split->path_disk, path, split->path_disk_size - 1);
|
||||
split->path_disk[split->path_disk_size - 1] = 0;
|
||||
|
||||
if ((mode & MZ_OPEN_MODE_WRITE) && ((mode & MZ_OPEN_MODE_APPEND) == 0))
|
||||
{
|
||||
number_disk = 0;
|
||||
split->current_disk = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
number_disk = -1;
|
||||
split->current_disk = 0;
|
||||
}
|
||||
|
||||
return mz_stream_split_goto_disk(stream, number_disk);
|
||||
}
|
||||
|
||||
int32_t mz_stream_split_is_open(void *stream)
|
||||
{
|
||||
mz_stream_split *split = (mz_stream_split *)stream;
|
||||
if (split->is_open != 1)
|
||||
return MZ_OPEN_ERROR;
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_stream_split_read(void *stream, void *buf, int32_t size)
|
||||
{
|
||||
mz_stream_split *split = (mz_stream_split *)stream;
|
||||
int32_t bytes_left = size;
|
||||
int32_t read = 0;
|
||||
int32_t err = MZ_OK;
|
||||
uint8_t *buf_ptr = (uint8_t *)buf;
|
||||
|
||||
err = mz_stream_split_goto_disk(stream, split->number_disk);
|
||||
if (err != MZ_OK)
|
||||
return err;
|
||||
|
||||
while (bytes_left > 0)
|
||||
{
|
||||
read = mz_stream_read(split->stream.base, buf_ptr, bytes_left);
|
||||
|
||||
mz_stream_split_print("Split - Read disk - %" PRId32 "\n", read);
|
||||
|
||||
if (read < 0)
|
||||
return read;
|
||||
if (read == 0)
|
||||
{
|
||||
if (split->current_disk < 0) /* No more disks to goto */
|
||||
break;
|
||||
err = mz_stream_split_goto_disk(stream, split->current_disk + 1);
|
||||
if (err == MZ_EXIST_ERROR)
|
||||
{
|
||||
split->current_disk = -1;
|
||||
break;
|
||||
}
|
||||
if (err != MZ_OK)
|
||||
return err;
|
||||
}
|
||||
|
||||
bytes_left -= read;
|
||||
buf_ptr += read;
|
||||
split->total_in += read;
|
||||
split->total_in_disk += read;
|
||||
}
|
||||
return size - bytes_left;
|
||||
}
|
||||
|
||||
int32_t mz_stream_split_write(void *stream, const void *buf, int32_t size)
|
||||
{
|
||||
mz_stream_split *split = (mz_stream_split *)stream;
|
||||
int64_t position = 0;
|
||||
int32_t written = 0;
|
||||
int32_t bytes_left = size;
|
||||
int32_t bytes_to_write = 0;
|
||||
int32_t bytes_avail = 0;
|
||||
int32_t number_disk = -1;
|
||||
int32_t err = MZ_OK;
|
||||
const uint8_t *buf_ptr = (const uint8_t *)buf;
|
||||
|
||||
position = mz_stream_tell(split->stream.base);
|
||||
|
||||
while (bytes_left > 0)
|
||||
{
|
||||
bytes_to_write = bytes_left;
|
||||
|
||||
if (split->disk_size > 0)
|
||||
{
|
||||
if ((split->total_out_disk == split->disk_size && split->total_out > 0) ||
|
||||
(split->number_disk == -1 && split->number_disk != split->current_disk))
|
||||
{
|
||||
if (split->number_disk != -1)
|
||||
number_disk = split->current_disk + 1;
|
||||
|
||||
err = mz_stream_split_goto_disk(stream, number_disk);
|
||||
if (err != MZ_OK)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (split->number_disk != -1)
|
||||
{
|
||||
bytes_avail = (int32_t)(split->disk_size - split->total_out_disk);
|
||||
if (bytes_to_write > bytes_avail)
|
||||
bytes_to_write = bytes_avail;
|
||||
}
|
||||
}
|
||||
|
||||
written = mz_stream_write(split->stream.base, buf_ptr, bytes_to_write);
|
||||
if (written != bytes_to_write)
|
||||
return MZ_WRITE_ERROR;
|
||||
|
||||
mz_stream_split_print("Split - Write disk - %" PRId32 "\n", written);
|
||||
|
||||
bytes_left -= written;
|
||||
buf_ptr += written;
|
||||
|
||||
split->total_out += written;
|
||||
split->total_out_disk += written;
|
||||
|
||||
if (position == split->current_disk_size)
|
||||
{
|
||||
split->current_disk_size += written;
|
||||
position = split->current_disk_size;
|
||||
}
|
||||
}
|
||||
|
||||
return size - bytes_left;
|
||||
}
|
||||
|
||||
int64_t mz_stream_split_tell(void *stream)
|
||||
{
|
||||
mz_stream_split *split = (mz_stream_split *)stream;
|
||||
int32_t err = MZ_OK;
|
||||
err = mz_stream_split_goto_disk(stream, split->number_disk);
|
||||
if (err != MZ_OK)
|
||||
return err;
|
||||
return mz_stream_tell(split->stream.base);
|
||||
}
|
||||
|
||||
int32_t mz_stream_split_seek(void *stream, int64_t offset, int32_t origin)
|
||||
{
|
||||
mz_stream_split *split = (mz_stream_split *)stream;
|
||||
int64_t disk_left = 0;
|
||||
int64_t position = 0;
|
||||
int32_t err = MZ_OK;
|
||||
|
||||
err = mz_stream_split_goto_disk(stream, split->number_disk);
|
||||
|
||||
if (err != MZ_OK)
|
||||
return err;
|
||||
|
||||
mz_stream_split_print("Split - Seek disk - %" PRId64 " (origin %" PRId32 ")\n", offset, origin);
|
||||
|
||||
if ((origin == MZ_SEEK_CUR) && (split->number_disk != -1))
|
||||
{
|
||||
position = mz_stream_tell(split->stream.base);
|
||||
disk_left = split->current_disk_size - position;
|
||||
|
||||
while (offset > disk_left)
|
||||
{
|
||||
err = mz_stream_split_goto_disk(stream, split->current_disk + 1);
|
||||
if (err != MZ_OK)
|
||||
return err;
|
||||
|
||||
offset -= disk_left;
|
||||
disk_left = split->current_disk_size;
|
||||
}
|
||||
}
|
||||
|
||||
return mz_stream_seek(split->stream.base, offset, origin);
|
||||
}
|
||||
|
||||
int32_t mz_stream_split_close(void *stream)
|
||||
{
|
||||
mz_stream_split *split = (mz_stream_split *)stream;
|
||||
int32_t err = MZ_OK;
|
||||
|
||||
err = mz_stream_split_close_disk(stream);
|
||||
split->is_open = 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
int32_t mz_stream_split_error(void *stream)
|
||||
{
|
||||
mz_stream_split *split = (mz_stream_split *)stream;
|
||||
return mz_stream_error(split->stream.base);
|
||||
}
|
||||
|
||||
int32_t mz_stream_split_get_prop_int64(void *stream, int32_t prop, int64_t *value)
|
||||
{
|
||||
mz_stream_split *split = (mz_stream_split *)stream;
|
||||
switch (prop)
|
||||
{
|
||||
case MZ_STREAM_PROP_TOTAL_OUT:
|
||||
*value = split->total_out;
|
||||
break;
|
||||
case MZ_STREAM_PROP_DISK_NUMBER:
|
||||
*value = split->number_disk;
|
||||
break;
|
||||
case MZ_STREAM_PROP_DISK_SIZE:
|
||||
*value = split->disk_size;
|
||||
break;
|
||||
default:
|
||||
return MZ_EXIST_ERROR;
|
||||
}
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_stream_split_set_prop_int64(void *stream, int32_t prop, int64_t value)
|
||||
{
|
||||
mz_stream_split *split = (mz_stream_split *)stream;
|
||||
switch (prop)
|
||||
{
|
||||
case MZ_STREAM_PROP_DISK_NUMBER:
|
||||
split->number_disk = (int32_t)value;
|
||||
break;
|
||||
case MZ_STREAM_PROP_DISK_SIZE:
|
||||
split->disk_size = value;
|
||||
break;
|
||||
default:
|
||||
return MZ_EXIST_ERROR;
|
||||
}
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
void *mz_stream_split_create(void **stream)
|
||||
{
|
||||
mz_stream_split *split = NULL;
|
||||
|
||||
split = (mz_stream_split *)MZ_ALLOC(sizeof(mz_stream_split));
|
||||
if (split != NULL)
|
||||
{
|
||||
memset(split, 0, sizeof(mz_stream_split));
|
||||
split->stream.vtbl = &mz_stream_split_vtbl;
|
||||
}
|
||||
if (stream != NULL)
|
||||
*stream = split;
|
||||
|
||||
return split;
|
||||
}
|
||||
|
||||
void mz_stream_split_delete(void **stream)
|
||||
{
|
||||
mz_stream_split *split = NULL;
|
||||
if (stream == NULL)
|
||||
return;
|
||||
split = (mz_stream_split *)*stream;
|
||||
if (split != NULL)
|
||||
{
|
||||
if (split->path_cd)
|
||||
MZ_FREE(split->path_cd);
|
||||
if (split->path_disk)
|
||||
MZ_FREE(split->path_disk);
|
||||
|
||||
MZ_FREE(split);
|
||||
}
|
||||
*stream = NULL;
|
||||
}
|
||||
|
||||
void *mz_stream_split_get_interface(void)
|
||||
{
|
||||
return (void *)&mz_stream_split_vtbl;
|
||||
}
|
44
third-party/ZipArchive/Sources/minizip/mz_strm_split.h
vendored
Normal file
44
third-party/ZipArchive/Sources/minizip/mz_strm_split.h
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
/* mz_strm_split.h -- Stream for split files
|
||||
Version 2.9.2, February 12, 2020
|
||||
part of MiniZip project
|
||||
|
||||
Copyright (C) 2010-2020 Nathan Moinvaziri
|
||||
https://github.com/nmoinvaz/minizip
|
||||
|
||||
This program is distributed under the terms of the same license as zlib.
|
||||
See the accompanying LICENSE file for the full text of the license.
|
||||
*/
|
||||
|
||||
#ifndef MZ_STREAM_SPLIT_H
|
||||
#define MZ_STREAM_SPLIT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_stream_split_open(void *stream, const char *filename, int32_t mode);
|
||||
int32_t mz_stream_split_is_open(void *stream);
|
||||
int32_t mz_stream_split_read(void *stream, void *buf, int32_t size);
|
||||
int32_t mz_stream_split_write(void *stream, const void *buf, int32_t size);
|
||||
int64_t mz_stream_split_tell(void *stream);
|
||||
int32_t mz_stream_split_seek(void *stream, int64_t offset, int32_t origin);
|
||||
int32_t mz_stream_split_close(void *stream);
|
||||
int32_t mz_stream_split_error(void *stream);
|
||||
|
||||
int32_t mz_stream_split_get_prop_int64(void *stream, int32_t prop, int64_t *value);
|
||||
int32_t mz_stream_split_set_prop_int64(void *stream, int32_t prop, int64_t value);
|
||||
|
||||
void* mz_stream_split_create(void **stream);
|
||||
void mz_stream_split_delete(void **stream);
|
||||
|
||||
void* mz_stream_split_get_interface(void);
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
405
third-party/ZipArchive/Sources/minizip/mz_strm_wzaes.c
vendored
Normal file
405
third-party/ZipArchive/Sources/minizip/mz_strm_wzaes.c
vendored
Normal file
@ -0,0 +1,405 @@
|
||||
/* mz_strm_wzaes.c -- Stream for WinZip AES encryption
|
||||
Version 2.9.2, February 12, 2020
|
||||
part of the MiniZip project
|
||||
|
||||
Copyright (C) 2010-2020 Nathan Moinvaziri
|
||||
https://github.com/nmoinvaz/minizip
|
||||
Copyright (C) 1998-2010 Brian Gladman, Worcester, UK
|
||||
|
||||
This program is distributed under the terms of the same license as zlib.
|
||||
See the accompanying LICENSE file for the full text of the license.
|
||||
*/
|
||||
|
||||
|
||||
#include "mz.h"
|
||||
#include "mz_crypt.h"
|
||||
#include "mz_strm.h"
|
||||
#include "mz_strm_wzaes.h"
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#define MZ_AES_KEYING_ITERATIONS (1000)
|
||||
#define MZ_AES_SALT_LENGTH(MODE) (4 * (MODE & 3) + 4)
|
||||
#define MZ_AES_SALT_LENGTH_MAX (16)
|
||||
#define MZ_AES_PW_LENGTH_MAX (128)
|
||||
#define MZ_AES_PW_VERIFY_SIZE (2)
|
||||
#define MZ_AES_AUTHCODE_SIZE (10)
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
static mz_stream_vtbl mz_stream_wzaes_vtbl = {
|
||||
mz_stream_wzaes_open,
|
||||
mz_stream_wzaes_is_open,
|
||||
mz_stream_wzaes_read,
|
||||
mz_stream_wzaes_write,
|
||||
mz_stream_wzaes_tell,
|
||||
mz_stream_wzaes_seek,
|
||||
mz_stream_wzaes_close,
|
||||
mz_stream_wzaes_error,
|
||||
mz_stream_wzaes_create,
|
||||
mz_stream_wzaes_delete,
|
||||
mz_stream_wzaes_get_prop_int64,
|
||||
mz_stream_wzaes_set_prop_int64
|
||||
};
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
typedef struct mz_stream_wzaes_s {
|
||||
mz_stream stream;
|
||||
int32_t mode;
|
||||
int32_t error;
|
||||
int16_t initialized;
|
||||
uint8_t buffer[UINT16_MAX];
|
||||
int64_t total_in;
|
||||
int64_t max_total_in;
|
||||
int64_t total_out;
|
||||
int16_t encryption_mode;
|
||||
const char *password;
|
||||
void *aes;
|
||||
uint32_t crypt_pos;
|
||||
uint8_t crypt_block[MZ_AES_BLOCK_SIZE];
|
||||
void *hmac;
|
||||
uint8_t nonce[MZ_AES_BLOCK_SIZE];
|
||||
} mz_stream_wzaes;
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_stream_wzaes_open(void *stream, const char *path, int32_t mode)
|
||||
{
|
||||
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
|
||||
uint16_t salt_length = 0;
|
||||
uint16_t password_length = 0;
|
||||
uint16_t key_length = 0;
|
||||
uint8_t kbuf[2 * MZ_AES_KEY_LENGTH_MAX + MZ_AES_PW_VERIFY_SIZE];
|
||||
uint8_t verify[MZ_AES_PW_VERIFY_SIZE];
|
||||
uint8_t verify_expected[MZ_AES_PW_VERIFY_SIZE];
|
||||
uint8_t salt_value[MZ_AES_SALT_LENGTH_MAX];
|
||||
const char *password = path;
|
||||
|
||||
wzaes->total_in = 0;
|
||||
wzaes->total_out = 0;
|
||||
wzaes->initialized = 0;
|
||||
|
||||
if (mz_stream_is_open(wzaes->stream.base) != MZ_OK)
|
||||
return MZ_OPEN_ERROR;
|
||||
|
||||
if (password == NULL)
|
||||
password = wzaes->password;
|
||||
if (password == NULL)
|
||||
return MZ_PARAM_ERROR;
|
||||
password_length = (uint16_t)strlen(password);
|
||||
if (password_length > MZ_AES_PW_LENGTH_MAX)
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
if (wzaes->encryption_mode < 1 || wzaes->encryption_mode > 3)
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
salt_length = MZ_AES_SALT_LENGTH(wzaes->encryption_mode);
|
||||
|
||||
if (mode & MZ_OPEN_MODE_WRITE)
|
||||
{
|
||||
#ifdef MZ_ZIP_NO_COMPRESSION
|
||||
return MZ_SUPPORT_ERROR;
|
||||
#else
|
||||
mz_crypt_rand(salt_value, salt_length);
|
||||
#endif
|
||||
}
|
||||
else if (mode & MZ_OPEN_MODE_READ)
|
||||
{
|
||||
#ifdef MZ_ZIP_NO_DECOMPRESSION
|
||||
return MZ_SUPPORT_ERROR;
|
||||
#else
|
||||
if (mz_stream_read(wzaes->stream.base, salt_value, salt_length) != salt_length)
|
||||
return MZ_READ_ERROR;
|
||||
#endif
|
||||
}
|
||||
|
||||
key_length = MZ_AES_KEY_LENGTH(wzaes->encryption_mode);
|
||||
|
||||
/* Derive the encryption and authentication keys and the password verifier */
|
||||
mz_crypt_pbkdf2((uint8_t *)password, password_length, salt_value, salt_length,
|
||||
MZ_AES_KEYING_ITERATIONS, kbuf, 2 * key_length + MZ_AES_PW_VERIFY_SIZE);
|
||||
|
||||
/* Initialize the encryption nonce and buffer pos */
|
||||
wzaes->crypt_pos = MZ_AES_BLOCK_SIZE;
|
||||
memset(wzaes->nonce, 0, sizeof(wzaes->nonce));
|
||||
|
||||
/* Initialize for encryption using key 1 */
|
||||
mz_crypt_aes_reset(wzaes->aes);
|
||||
mz_crypt_aes_set_mode(wzaes->aes, wzaes->encryption_mode);
|
||||
mz_crypt_aes_set_encrypt_key(wzaes->aes, kbuf, key_length);
|
||||
|
||||
/* Initialize for authentication using key 2 */
|
||||
mz_crypt_hmac_reset(wzaes->hmac);
|
||||
mz_crypt_hmac_set_algorithm(wzaes->hmac, MZ_HASH_SHA1);
|
||||
mz_crypt_hmac_init(wzaes->hmac, kbuf + key_length, key_length);
|
||||
|
||||
memcpy(verify, kbuf + (2 * key_length), MZ_AES_PW_VERIFY_SIZE);
|
||||
|
||||
if (mode & MZ_OPEN_MODE_WRITE)
|
||||
{
|
||||
if (mz_stream_write(wzaes->stream.base, salt_value, salt_length) != salt_length)
|
||||
return MZ_WRITE_ERROR;
|
||||
|
||||
wzaes->total_out += salt_length;
|
||||
|
||||
if (mz_stream_write(wzaes->stream.base, verify, MZ_AES_PW_VERIFY_SIZE) != MZ_AES_PW_VERIFY_SIZE)
|
||||
return MZ_WRITE_ERROR;
|
||||
|
||||
wzaes->total_out += MZ_AES_PW_VERIFY_SIZE;
|
||||
}
|
||||
else if (mode & MZ_OPEN_MODE_READ)
|
||||
{
|
||||
wzaes->total_in += salt_length;
|
||||
|
||||
if (mz_stream_read(wzaes->stream.base, verify_expected, MZ_AES_PW_VERIFY_SIZE) != MZ_AES_PW_VERIFY_SIZE)
|
||||
return MZ_READ_ERROR;
|
||||
|
||||
wzaes->total_in += MZ_AES_PW_VERIFY_SIZE;
|
||||
|
||||
if (memcmp(verify_expected, verify, MZ_AES_PW_VERIFY_SIZE) != 0)
|
||||
return MZ_PASSWORD_ERROR;
|
||||
}
|
||||
|
||||
wzaes->mode = mode;
|
||||
wzaes->initialized = 1;
|
||||
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_stream_wzaes_is_open(void *stream)
|
||||
{
|
||||
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
|
||||
if (wzaes->initialized == 0)
|
||||
return MZ_OPEN_ERROR;
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
static int32_t mz_stream_wzaes_ctr_encrypt(void *stream, uint8_t *buf, int32_t size)
|
||||
{
|
||||
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
|
||||
uint32_t pos = wzaes->crypt_pos;
|
||||
uint32_t i = 0;
|
||||
int32_t err = MZ_OK;
|
||||
|
||||
while (i < (uint32_t)size)
|
||||
{
|
||||
if (pos == MZ_AES_BLOCK_SIZE)
|
||||
{
|
||||
uint32_t j = 0;
|
||||
|
||||
/* Increment encryption nonce */
|
||||
while (j < 8 && !++wzaes->nonce[j])
|
||||
j += 1;
|
||||
|
||||
/* Encrypt the nonce to form next xor buffer */
|
||||
memcpy(wzaes->crypt_block, wzaes->nonce, MZ_AES_BLOCK_SIZE);
|
||||
mz_crypt_aes_encrypt(wzaes->aes, wzaes->crypt_block, sizeof(wzaes->crypt_block));
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
buf[i++] ^= wzaes->crypt_block[pos++];
|
||||
}
|
||||
|
||||
wzaes->crypt_pos = pos;
|
||||
return err;
|
||||
}
|
||||
|
||||
int32_t mz_stream_wzaes_read(void *stream, void *buf, int32_t size)
|
||||
{
|
||||
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
|
||||
int64_t max_total_in = 0;
|
||||
int32_t bytes_to_read = size;
|
||||
int32_t read = 0;
|
||||
|
||||
max_total_in = wzaes->max_total_in - MZ_AES_FOOTER_SIZE;
|
||||
if ((int64_t)bytes_to_read > (max_total_in - wzaes->total_in))
|
||||
bytes_to_read = (int32_t)(max_total_in - wzaes->total_in);
|
||||
|
||||
read = mz_stream_read(wzaes->stream.base, buf, bytes_to_read);
|
||||
|
||||
if (read > 0)
|
||||
{
|
||||
mz_crypt_hmac_update(wzaes->hmac, (uint8_t *)buf, read);
|
||||
mz_stream_wzaes_ctr_encrypt(stream, (uint8_t *)buf, read);
|
||||
|
||||
wzaes->total_in += read;
|
||||
}
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
int32_t mz_stream_wzaes_write(void *stream, const void *buf, int32_t size)
|
||||
{
|
||||
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
|
||||
const uint8_t *buf_ptr = (const uint8_t *)buf;
|
||||
int32_t bytes_to_write = sizeof(wzaes->buffer);
|
||||
int32_t total_written = 0;
|
||||
int32_t written = 0;
|
||||
|
||||
if (size < 0)
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
do
|
||||
{
|
||||
if (bytes_to_write > (size - total_written))
|
||||
bytes_to_write = (size - total_written);
|
||||
|
||||
memcpy(wzaes->buffer, buf_ptr, bytes_to_write);
|
||||
buf_ptr += bytes_to_write;
|
||||
|
||||
mz_stream_wzaes_ctr_encrypt(stream, (uint8_t *)wzaes->buffer, bytes_to_write);
|
||||
mz_crypt_hmac_update(wzaes->hmac, wzaes->buffer, bytes_to_write);
|
||||
|
||||
written = mz_stream_write(wzaes->stream.base, wzaes->buffer, bytes_to_write);
|
||||
if (written < 0)
|
||||
return written;
|
||||
|
||||
total_written += written;
|
||||
}
|
||||
while (total_written < size && written > 0);
|
||||
|
||||
wzaes->total_out += total_written;
|
||||
return total_written;
|
||||
}
|
||||
|
||||
int64_t mz_stream_wzaes_tell(void *stream)
|
||||
{
|
||||
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
|
||||
return mz_stream_tell(wzaes->stream.base);
|
||||
}
|
||||
|
||||
int32_t mz_stream_wzaes_seek(void *stream, int64_t offset, int32_t origin)
|
||||
{
|
||||
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
|
||||
return mz_stream_seek(wzaes->stream.base, offset, origin);
|
||||
}
|
||||
|
||||
int32_t mz_stream_wzaes_close(void *stream)
|
||||
{
|
||||
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
|
||||
uint8_t expected_hash[MZ_AES_AUTHCODE_SIZE];
|
||||
uint8_t computed_hash[MZ_HASH_SHA1_SIZE];
|
||||
|
||||
mz_crypt_hmac_end(wzaes->hmac, computed_hash, sizeof(computed_hash));
|
||||
|
||||
if (wzaes->mode & MZ_OPEN_MODE_WRITE)
|
||||
{
|
||||
if (mz_stream_write(wzaes->stream.base, computed_hash, MZ_AES_AUTHCODE_SIZE) != MZ_AES_AUTHCODE_SIZE)
|
||||
return MZ_WRITE_ERROR;
|
||||
|
||||
wzaes->total_out += MZ_AES_AUTHCODE_SIZE;
|
||||
}
|
||||
else if (wzaes->mode & MZ_OPEN_MODE_READ)
|
||||
{
|
||||
if (mz_stream_read(wzaes->stream.base, expected_hash, MZ_AES_AUTHCODE_SIZE) != MZ_AES_AUTHCODE_SIZE)
|
||||
return MZ_READ_ERROR;
|
||||
|
||||
wzaes->total_in += MZ_AES_AUTHCODE_SIZE;
|
||||
|
||||
/* If entire entry was not read this will fail */
|
||||
if (memcmp(computed_hash, expected_hash, MZ_AES_AUTHCODE_SIZE) != 0)
|
||||
return MZ_CRC_ERROR;
|
||||
}
|
||||
|
||||
wzaes->initialized = 0;
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_stream_wzaes_error(void *stream)
|
||||
{
|
||||
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
|
||||
return wzaes->error;
|
||||
}
|
||||
|
||||
void mz_stream_wzaes_set_password(void *stream, const char *password)
|
||||
{
|
||||
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
|
||||
wzaes->password = password;
|
||||
}
|
||||
|
||||
void mz_stream_wzaes_set_encryption_mode(void *stream, int16_t encryption_mode)
|
||||
{
|
||||
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
|
||||
wzaes->encryption_mode = encryption_mode;
|
||||
}
|
||||
|
||||
int32_t mz_stream_wzaes_get_prop_int64(void *stream, int32_t prop, int64_t *value)
|
||||
{
|
||||
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
|
||||
switch (prop)
|
||||
{
|
||||
case MZ_STREAM_PROP_TOTAL_IN:
|
||||
*value = wzaes->total_in;
|
||||
break;
|
||||
case MZ_STREAM_PROP_TOTAL_OUT:
|
||||
*value = wzaes->total_out;
|
||||
break;
|
||||
case MZ_STREAM_PROP_TOTAL_IN_MAX:
|
||||
*value = wzaes->max_total_in;
|
||||
break;
|
||||
case MZ_STREAM_PROP_HEADER_SIZE:
|
||||
*value = MZ_AES_SALT_LENGTH((int64_t)wzaes->encryption_mode) + MZ_AES_PW_VERIFY_SIZE;
|
||||
break;
|
||||
case MZ_STREAM_PROP_FOOTER_SIZE:
|
||||
*value = MZ_AES_AUTHCODE_SIZE;
|
||||
break;
|
||||
default:
|
||||
return MZ_EXIST_ERROR;
|
||||
}
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_stream_wzaes_set_prop_int64(void *stream, int32_t prop, int64_t value)
|
||||
{
|
||||
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
|
||||
switch (prop)
|
||||
{
|
||||
case MZ_STREAM_PROP_TOTAL_IN_MAX:
|
||||
wzaes->max_total_in = value;
|
||||
break;
|
||||
default:
|
||||
return MZ_EXIST_ERROR;
|
||||
}
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
void *mz_stream_wzaes_create(void **stream)
|
||||
{
|
||||
mz_stream_wzaes *wzaes = NULL;
|
||||
|
||||
wzaes = (mz_stream_wzaes *)MZ_ALLOC(sizeof(mz_stream_wzaes));
|
||||
if (wzaes != NULL)
|
||||
{
|
||||
memset(wzaes, 0, sizeof(mz_stream_wzaes));
|
||||
wzaes->stream.vtbl = &mz_stream_wzaes_vtbl;
|
||||
wzaes->encryption_mode = MZ_AES_ENCRYPTION_MODE_256;
|
||||
|
||||
mz_crypt_hmac_create(&wzaes->hmac);
|
||||
mz_crypt_aes_create(&wzaes->aes);
|
||||
}
|
||||
if (stream != NULL)
|
||||
*stream = wzaes;
|
||||
|
||||
return wzaes;
|
||||
}
|
||||
|
||||
void mz_stream_wzaes_delete(void **stream)
|
||||
{
|
||||
mz_stream_wzaes *wzaes = NULL;
|
||||
if (stream == NULL)
|
||||
return;
|
||||
wzaes = (mz_stream_wzaes *)*stream;
|
||||
if (wzaes != NULL)
|
||||
{
|
||||
mz_crypt_aes_delete(&wzaes->aes);
|
||||
mz_crypt_hmac_delete(&wzaes->hmac);
|
||||
MZ_FREE(wzaes);
|
||||
}
|
||||
*stream = NULL;
|
||||
}
|
||||
|
||||
void *mz_stream_wzaes_get_interface(void)
|
||||
{
|
||||
return (void *)&mz_stream_wzaes_vtbl;
|
||||
}
|
47
third-party/ZipArchive/Sources/minizip/mz_strm_wzaes.h
vendored
Normal file
47
third-party/ZipArchive/Sources/minizip/mz_strm_wzaes.h
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
/* mz_strm_wzaes.h -- Stream for WinZIP AES encryption
|
||||
Version 2.9.2, February 12, 2020
|
||||
part of the MiniZip project
|
||||
|
||||
Copyright (C) 2010-2020 Nathan Moinvaziri
|
||||
https://github.com/nmoinvaz/minizip
|
||||
|
||||
This program is distributed under the terms of the same license as zlib.
|
||||
See the accompanying LICENSE file for the full text of the license.
|
||||
*/
|
||||
|
||||
#ifndef MZ_STREAM_WZAES_SHA1_H
|
||||
#define MZ_STREAM_WZAES_SHA1_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_stream_wzaes_open(void *stream, const char *filename, int32_t mode);
|
||||
int32_t mz_stream_wzaes_is_open(void *stream);
|
||||
int32_t mz_stream_wzaes_read(void *stream, void *buf, int32_t size);
|
||||
int32_t mz_stream_wzaes_write(void *stream, const void *buf, int32_t size);
|
||||
int64_t mz_stream_wzaes_tell(void *stream);
|
||||
int32_t mz_stream_wzaes_seek(void *stream, int64_t offset, int32_t origin);
|
||||
int32_t mz_stream_wzaes_close(void *stream);
|
||||
int32_t mz_stream_wzaes_error(void *stream);
|
||||
|
||||
void mz_stream_wzaes_set_password(void *stream, const char *password);
|
||||
void mz_stream_wzaes_set_encryption_mode(void *stream, int16_t encryption_mode);
|
||||
|
||||
int32_t mz_stream_wzaes_get_prop_int64(void *stream, int32_t prop, int64_t *value);
|
||||
int32_t mz_stream_wzaes_set_prop_int64(void *stream, int32_t prop, int64_t value);
|
||||
|
||||
void* mz_stream_wzaes_create(void **stream);
|
||||
void mz_stream_wzaes_delete(void **stream);
|
||||
|
||||
void* mz_stream_wzaes_get_interface(void);
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
425
third-party/ZipArchive/Sources/minizip/mz_strm_zlib.c
vendored
Normal file
425
third-party/ZipArchive/Sources/minizip/mz_strm_zlib.c
vendored
Normal file
@ -0,0 +1,425 @@
|
||||
/* mz_strm_zlib.c -- Stream for zlib inflate/deflate
|
||||
Version 2.9.2, February 12, 2020
|
||||
part of the MiniZip project
|
||||
|
||||
Copyright (C) 2010-2020 Nathan Moinvaziri
|
||||
https://github.com/nmoinvaz/minizip
|
||||
|
||||
This program is distributed under the terms of the same license as zlib.
|
||||
See the accompanying LICENSE file for the full text of the license.
|
||||
*/
|
||||
|
||||
|
||||
#include "mz.h"
|
||||
#include "mz_strm.h"
|
||||
#include "mz_strm_zlib.h"
|
||||
|
||||
#include "zlib.h"
|
||||
#if defined(ZLIBNG_VERNUM) && !defined(ZLIB_COMPAT)
|
||||
# include "zlib-ng.h"
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#if defined(ZLIBNG_VERNUM) && !defined(ZLIB_COMPAT)
|
||||
# define ZLIB_PREFIX(x) zng_ ## x
|
||||
typedef zng_stream zlib_stream;
|
||||
#else
|
||||
# define ZLIB_PREFIX(x) x
|
||||
typedef z_stream zlib_stream;
|
||||
#endif
|
||||
|
||||
#if !defined(DEF_MEM_LEVEL)
|
||||
# if MAX_MEM_LEVEL >= 8
|
||||
# define DEF_MEM_LEVEL 8
|
||||
# else
|
||||
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
static mz_stream_vtbl mz_stream_zlib_vtbl = {
|
||||
mz_stream_zlib_open,
|
||||
mz_stream_zlib_is_open,
|
||||
mz_stream_zlib_read,
|
||||
mz_stream_zlib_write,
|
||||
mz_stream_zlib_tell,
|
||||
mz_stream_zlib_seek,
|
||||
mz_stream_zlib_close,
|
||||
mz_stream_zlib_error,
|
||||
mz_stream_zlib_create,
|
||||
mz_stream_zlib_delete,
|
||||
mz_stream_zlib_get_prop_int64,
|
||||
mz_stream_zlib_set_prop_int64
|
||||
};
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
typedef struct mz_stream_zlib_s {
|
||||
mz_stream stream;
|
||||
zlib_stream zstream;
|
||||
uint8_t buffer[INT16_MAX];
|
||||
int32_t buffer_len;
|
||||
int64_t total_in;
|
||||
int64_t total_out;
|
||||
int64_t max_total_in;
|
||||
int8_t initialized;
|
||||
int16_t level;
|
||||
int32_t window_bits;
|
||||
int32_t mode;
|
||||
int32_t error;
|
||||
} mz_stream_zlib;
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_stream_zlib_open(void *stream, const char *path, int32_t mode)
|
||||
{
|
||||
mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
|
||||
|
||||
MZ_UNUSED(path);
|
||||
|
||||
zlib->zstream.data_type = Z_BINARY;
|
||||
zlib->zstream.zalloc = Z_NULL;
|
||||
zlib->zstream.zfree = Z_NULL;
|
||||
zlib->zstream.opaque = Z_NULL;
|
||||
zlib->zstream.total_in = 0;
|
||||
zlib->zstream.total_out = 0;
|
||||
|
||||
zlib->total_in = 0;
|
||||
zlib->total_out = 0;
|
||||
|
||||
if (mode & MZ_OPEN_MODE_WRITE)
|
||||
{
|
||||
#ifdef MZ_ZIP_NO_COMPRESSION
|
||||
return MZ_SUPPORT_ERROR;
|
||||
#else
|
||||
zlib->zstream.next_out = zlib->buffer;
|
||||
zlib->zstream.avail_out = sizeof(zlib->buffer);
|
||||
|
||||
zlib->error = ZLIB_PREFIX(deflateInit2)(&zlib->zstream, (int8_t)zlib->level, Z_DEFLATED,
|
||||
zlib->window_bits, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
|
||||
#endif
|
||||
}
|
||||
else if (mode & MZ_OPEN_MODE_READ)
|
||||
{
|
||||
#ifdef MZ_ZIP_NO_DECOMPRESSION
|
||||
return MZ_SUPPORT_ERROR;
|
||||
#else
|
||||
zlib->zstream.next_in = zlib->buffer;
|
||||
zlib->zstream.avail_in = 0;
|
||||
|
||||
zlib->error = ZLIB_PREFIX(inflateInit2)(&zlib->zstream, zlib->window_bits);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (zlib->error != Z_OK)
|
||||
return MZ_OPEN_ERROR;
|
||||
|
||||
zlib->initialized = 1;
|
||||
zlib->mode = mode;
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_stream_zlib_is_open(void *stream)
|
||||
{
|
||||
mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
|
||||
if (zlib->initialized != 1)
|
||||
return MZ_OPEN_ERROR;
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_stream_zlib_read(void *stream, void *buf, int32_t size)
|
||||
{
|
||||
#ifdef MZ_ZIP_NO_DECOMPRESSION
|
||||
MZ_UNUSED(stream);
|
||||
MZ_UNUSED(buf);
|
||||
MZ_UNUSED(size);
|
||||
return MZ_SUPPORT_ERROR;
|
||||
#else
|
||||
mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
|
||||
uint64_t total_in_before = 0;
|
||||
uint64_t total_in_after = 0;
|
||||
uint64_t total_out_before = 0;
|
||||
uint64_t total_out_after = 0;
|
||||
uint32_t total_in = 0;
|
||||
uint32_t total_out = 0;
|
||||
uint32_t in_bytes = 0;
|
||||
uint32_t out_bytes = 0;
|
||||
int32_t bytes_to_read = sizeof(zlib->buffer);
|
||||
int32_t read = 0;
|
||||
int32_t err = Z_OK;
|
||||
|
||||
|
||||
zlib->zstream.next_out = (Bytef*)buf;
|
||||
zlib->zstream.avail_out = (uInt)size;
|
||||
|
||||
do
|
||||
{
|
||||
if (zlib->zstream.avail_in == 0)
|
||||
{
|
||||
if (zlib->max_total_in > 0)
|
||||
{
|
||||
if ((int64_t)bytes_to_read > (zlib->max_total_in - zlib->total_in))
|
||||
bytes_to_read = (int32_t)(zlib->max_total_in - zlib->total_in);
|
||||
}
|
||||
|
||||
read = mz_stream_read(zlib->stream.base, zlib->buffer, bytes_to_read);
|
||||
|
||||
if (read < 0)
|
||||
return read;
|
||||
|
||||
zlib->zstream.next_in = zlib->buffer;
|
||||
zlib->zstream.avail_in = read;
|
||||
}
|
||||
|
||||
total_in_before = zlib->zstream.avail_in;
|
||||
total_out_before = zlib->zstream.total_out;
|
||||
|
||||
err = ZLIB_PREFIX(inflate)(&zlib->zstream, Z_SYNC_FLUSH);
|
||||
if ((err >= Z_OK) && (zlib->zstream.msg != NULL))
|
||||
{
|
||||
zlib->error = Z_DATA_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
total_in_after = zlib->zstream.avail_in;
|
||||
total_out_after = zlib->zstream.total_out;
|
||||
|
||||
in_bytes = (uint32_t)(total_in_before - total_in_after);
|
||||
out_bytes = (uint32_t)(total_out_after - total_out_before);
|
||||
|
||||
total_in += in_bytes;
|
||||
total_out += out_bytes;
|
||||
|
||||
zlib->total_in += in_bytes;
|
||||
zlib->total_out += out_bytes;
|
||||
|
||||
if (err == Z_STREAM_END)
|
||||
break;
|
||||
if (err != Z_OK)
|
||||
{
|
||||
zlib->error = err;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (zlib->zstream.avail_out > 0);
|
||||
|
||||
if (zlib->error != 0)
|
||||
{
|
||||
/* Zlib errors are compatible with MZ */
|
||||
return zlib->error;
|
||||
}
|
||||
|
||||
return total_out;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef MZ_ZIP_NO_COMPRESSION
|
||||
static int32_t mz_stream_zlib_flush(void *stream)
|
||||
{
|
||||
mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
|
||||
if (mz_stream_write(zlib->stream.base, zlib->buffer, zlib->buffer_len) != zlib->buffer_len)
|
||||
return MZ_WRITE_ERROR;
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
static int32_t mz_stream_zlib_deflate(void *stream, int flush)
|
||||
{
|
||||
mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
|
||||
uint64_t total_out_before = 0;
|
||||
uint64_t total_out_after = 0;
|
||||
int32_t out_bytes = 0;
|
||||
int32_t err = Z_OK;
|
||||
|
||||
|
||||
do
|
||||
{
|
||||
if (zlib->zstream.avail_out == 0)
|
||||
{
|
||||
err = mz_stream_zlib_flush(zlib);
|
||||
if (err != MZ_OK)
|
||||
return err;
|
||||
|
||||
zlib->zstream.avail_out = sizeof(zlib->buffer);
|
||||
zlib->zstream.next_out = zlib->buffer;
|
||||
|
||||
zlib->buffer_len = 0;
|
||||
}
|
||||
|
||||
total_out_before = zlib->zstream.total_out;
|
||||
err = ZLIB_PREFIX(deflate)(&zlib->zstream, flush);
|
||||
total_out_after = zlib->zstream.total_out;
|
||||
|
||||
out_bytes = (uint32_t)(total_out_after - total_out_before);
|
||||
|
||||
zlib->buffer_len += out_bytes;
|
||||
zlib->total_out += out_bytes;
|
||||
|
||||
if (err == Z_STREAM_END)
|
||||
break;
|
||||
if (err != Z_OK)
|
||||
{
|
||||
zlib->error = err;
|
||||
return MZ_DATA_ERROR;
|
||||
}
|
||||
}
|
||||
while ((zlib->zstream.avail_in > 0) || (flush == Z_FINISH && err == Z_OK));
|
||||
|
||||
return MZ_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
int32_t mz_stream_zlib_write(void *stream, const void *buf, int32_t size)
|
||||
{
|
||||
mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
|
||||
int32_t err = size;
|
||||
|
||||
#ifdef MZ_ZIP_NO_COMPRESSION
|
||||
MZ_UNUSED(zlib);
|
||||
MZ_UNUSED(buf);
|
||||
err = MZ_SUPPORT_ERROR;
|
||||
#else
|
||||
zlib->zstream.next_in = (Bytef*)(intptr_t)buf;
|
||||
zlib->zstream.avail_in = (uInt)size;
|
||||
|
||||
mz_stream_zlib_deflate(stream, Z_NO_FLUSH);
|
||||
|
||||
zlib->total_in += size;
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
int64_t mz_stream_zlib_tell(void *stream)
|
||||
{
|
||||
MZ_UNUSED(stream);
|
||||
|
||||
return MZ_TELL_ERROR;
|
||||
}
|
||||
|
||||
int32_t mz_stream_zlib_seek(void *stream, int64_t offset, int32_t origin)
|
||||
{
|
||||
MZ_UNUSED(stream);
|
||||
MZ_UNUSED(offset);
|
||||
MZ_UNUSED(origin);
|
||||
|
||||
return MZ_SEEK_ERROR;
|
||||
}
|
||||
|
||||
int32_t mz_stream_zlib_close(void *stream)
|
||||
{
|
||||
mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
|
||||
|
||||
|
||||
if (zlib->mode & MZ_OPEN_MODE_WRITE)
|
||||
{
|
||||
#ifdef MZ_ZIP_NO_COMPRESSION
|
||||
return MZ_SUPPORT_ERROR;
|
||||
#else
|
||||
mz_stream_zlib_deflate(stream, Z_FINISH);
|
||||
mz_stream_zlib_flush(stream);
|
||||
|
||||
ZLIB_PREFIX(deflateEnd)(&zlib->zstream);
|
||||
#endif
|
||||
}
|
||||
else if (zlib->mode & MZ_OPEN_MODE_READ)
|
||||
{
|
||||
#ifdef MZ_ZIP_NO_DECOMPRESSION
|
||||
return MZ_SUPPORT_ERROR;
|
||||
#else
|
||||
ZLIB_PREFIX(inflateEnd)(&zlib->zstream);
|
||||
#endif
|
||||
}
|
||||
|
||||
zlib->initialized = 0;
|
||||
|
||||
if (zlib->error != Z_OK)
|
||||
return MZ_CLOSE_ERROR;
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_stream_zlib_error(void *stream)
|
||||
{
|
||||
mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
|
||||
return zlib->error;
|
||||
}
|
||||
|
||||
int32_t mz_stream_zlib_get_prop_int64(void *stream, int32_t prop, int64_t *value)
|
||||
{
|
||||
mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
|
||||
switch (prop)
|
||||
{
|
||||
case MZ_STREAM_PROP_TOTAL_IN:
|
||||
*value = zlib->total_in;
|
||||
break;
|
||||
case MZ_STREAM_PROP_TOTAL_IN_MAX:
|
||||
*value = zlib->max_total_in;
|
||||
break;
|
||||
case MZ_STREAM_PROP_TOTAL_OUT:
|
||||
*value = zlib->total_out;
|
||||
break;
|
||||
case MZ_STREAM_PROP_HEADER_SIZE:
|
||||
*value = 0;
|
||||
break;
|
||||
case MZ_STREAM_PROP_COMPRESS_WINDOW:
|
||||
*value = zlib->window_bits;
|
||||
break;
|
||||
default:
|
||||
return MZ_EXIST_ERROR;
|
||||
}
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_stream_zlib_set_prop_int64(void *stream, int32_t prop, int64_t value)
|
||||
{
|
||||
mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
|
||||
switch (prop)
|
||||
{
|
||||
case MZ_STREAM_PROP_COMPRESS_LEVEL:
|
||||
zlib->level = (int16_t)value;
|
||||
break;
|
||||
case MZ_STREAM_PROP_TOTAL_IN_MAX:
|
||||
zlib->max_total_in = value;
|
||||
break;
|
||||
case MZ_STREAM_PROP_COMPRESS_WINDOW:
|
||||
zlib->window_bits = (int32_t)value;
|
||||
break;
|
||||
default:
|
||||
return MZ_EXIST_ERROR;
|
||||
}
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
void *mz_stream_zlib_create(void **stream)
|
||||
{
|
||||
mz_stream_zlib *zlib = NULL;
|
||||
|
||||
zlib = (mz_stream_zlib *)MZ_ALLOC(sizeof(mz_stream_zlib));
|
||||
if (zlib != NULL)
|
||||
{
|
||||
memset(zlib, 0, sizeof(mz_stream_zlib));
|
||||
zlib->stream.vtbl = &mz_stream_zlib_vtbl;
|
||||
zlib->level = Z_DEFAULT_COMPRESSION;
|
||||
zlib->window_bits = -MAX_WBITS;
|
||||
}
|
||||
if (stream != NULL)
|
||||
*stream = zlib;
|
||||
|
||||
return zlib;
|
||||
}
|
||||
|
||||
void mz_stream_zlib_delete(void **stream)
|
||||
{
|
||||
mz_stream_zlib *zlib = NULL;
|
||||
if (stream == NULL)
|
||||
return;
|
||||
zlib = (mz_stream_zlib *)*stream;
|
||||
if (zlib != NULL)
|
||||
MZ_FREE(zlib);
|
||||
*stream = NULL;
|
||||
}
|
||||
|
||||
void *mz_stream_zlib_get_interface(void)
|
||||
{
|
||||
return (void *)&mz_stream_zlib_vtbl;
|
||||
}
|
44
third-party/ZipArchive/Sources/minizip/mz_strm_zlib.h
vendored
Normal file
44
third-party/ZipArchive/Sources/minizip/mz_strm_zlib.h
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
/* mz_strm_zlib.h -- Stream for zlib inflate/deflate
|
||||
Version 2.9.2, February 12, 2020
|
||||
part of the MiniZip project
|
||||
|
||||
Copyright (C) 2010-2020 Nathan Moinvaziri
|
||||
https://github.com/nmoinvaz/minizip
|
||||
|
||||
This program is distributed under the terms of the same license as zlib.
|
||||
See the accompanying LICENSE file for the full text of the license.
|
||||
*/
|
||||
|
||||
#ifndef MZ_STREAM_ZLIB_H
|
||||
#define MZ_STREAM_ZLIB_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_stream_zlib_open(void *stream, const char *filename, int32_t mode);
|
||||
int32_t mz_stream_zlib_is_open(void *stream);
|
||||
int32_t mz_stream_zlib_read(void *stream, void *buf, int32_t size);
|
||||
int32_t mz_stream_zlib_write(void *stream, const void *buf, int32_t size);
|
||||
int64_t mz_stream_zlib_tell(void *stream);
|
||||
int32_t mz_stream_zlib_seek(void *stream, int64_t offset, int32_t origin);
|
||||
int32_t mz_stream_zlib_close(void *stream);
|
||||
int32_t mz_stream_zlib_error(void *stream);
|
||||
|
||||
int32_t mz_stream_zlib_get_prop_int64(void *stream, int32_t prop, int64_t *value);
|
||||
int32_t mz_stream_zlib_set_prop_int64(void *stream, int32_t prop, int64_t value);
|
||||
|
||||
void* mz_stream_zlib_create(void **stream);
|
||||
void mz_stream_zlib_delete(void **stream);
|
||||
|
||||
void* mz_stream_zlib_get_interface(void);
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
2917
third-party/ZipArchive/Sources/minizip/mz_zip.c
vendored
Normal file
2917
third-party/ZipArchive/Sources/minizip/mz_zip.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
251
third-party/ZipArchive/Sources/minizip/mz_zip.h
vendored
Normal file
251
third-party/ZipArchive/Sources/minizip/mz_zip.h
vendored
Normal file
@ -0,0 +1,251 @@
|
||||
/* mz_zip.h -- Zip manipulation
|
||||
Version 2.9.2, February 12, 2020
|
||||
part of the MiniZip project
|
||||
|
||||
Copyright (C) 2010-2020 Nathan Moinvaziri
|
||||
https://github.com/nmoinvaz/minizip
|
||||
Copyright (C) 2009-2010 Mathias Svensson
|
||||
Modifications for Zip64 support
|
||||
http://result42.com
|
||||
Copyright (C) 1998-2010 Gilles Vollant
|
||||
https://www.winimage.com/zLibDll/minizip.html
|
||||
|
||||
This program is distributed under the terms of the same license as zlib.
|
||||
See the accompanying LICENSE file for the full text of the license.
|
||||
*/
|
||||
|
||||
#ifndef MZ_ZIP_H
|
||||
#define MZ_ZIP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
typedef struct mz_zip_file_s
|
||||
{
|
||||
uint16_t version_madeby; /* version made by */
|
||||
uint16_t version_needed; /* version needed to extract */
|
||||
uint16_t flag; /* general purpose bit flag */
|
||||
uint16_t compression_method; /* compression method */
|
||||
time_t modified_date; /* last modified date in unix time */
|
||||
time_t accessed_date; /* last accessed date in unix time */
|
||||
time_t creation_date; /* creation date in unix time */
|
||||
uint32_t crc; /* crc-32 */
|
||||
int64_t compressed_size; /* compressed size */
|
||||
int64_t uncompressed_size; /* uncompressed size */
|
||||
uint16_t filename_size; /* filename length */
|
||||
uint16_t extrafield_size; /* extra field length */
|
||||
uint16_t comment_size; /* file comment length */
|
||||
uint32_t disk_number; /* disk number start */
|
||||
int64_t disk_offset; /* relative offset of local header */
|
||||
uint16_t internal_fa; /* internal file attributes */
|
||||
uint32_t external_fa; /* external file attributes */
|
||||
|
||||
const char *filename; /* filename utf8 null-terminated string */
|
||||
const uint8_t *extrafield; /* extrafield data */
|
||||
const char *comment; /* comment utf8 null-terminated string */
|
||||
const char *linkname; /* sym-link filename utf8 null-terminated string */
|
||||
|
||||
uint16_t zip64; /* zip64 extension mode */
|
||||
uint16_t aes_version; /* winzip aes extension if not 0 */
|
||||
uint8_t aes_encryption_mode; /* winzip aes encryption mode */
|
||||
|
||||
} mz_zip_file, mz_zip_entry;
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
typedef int32_t (*mz_zip_locate_entry_cb)(void *handle, void *userdata, mz_zip_file *file_info);
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
void * mz_zip_create(void **handle);
|
||||
/* Create zip instance for opening */
|
||||
|
||||
void mz_zip_delete(void **handle);
|
||||
/* Delete zip object */
|
||||
|
||||
int32_t mz_zip_open(void *handle, void *stream, int32_t mode);
|
||||
/* Create a zip file, no delete file in zip functionality */
|
||||
|
||||
int32_t mz_zip_close(void *handle);
|
||||
/* Close the zip file */
|
||||
|
||||
int32_t mz_zip_get_comment(void *handle, const char **comment);
|
||||
/* Get a pointer to the global comment */
|
||||
|
||||
int32_t mz_zip_set_comment(void *handle, const char *comment);
|
||||
/* Set the global comment used for writing zip file */
|
||||
|
||||
int32_t mz_zip_get_version_madeby(void *handle, uint16_t *version_madeby);
|
||||
/* Get the version made by */
|
||||
|
||||
int32_t mz_zip_set_version_madeby(void *handle, uint16_t version_madeby);
|
||||
/* Set the version made by used for writing zip file */
|
||||
|
||||
int32_t mz_zip_set_recover(void *handle, uint8_t recover);
|
||||
/* Set the ability to recover the central dir by reading local file headers */
|
||||
|
||||
int32_t mz_zip_set_data_descriptor(void *handle, uint8_t data_descriptor);
|
||||
/* Set the use of data descriptor flag when writing zip entries */
|
||||
|
||||
int32_t mz_zip_get_stream(void *handle, void **stream);
|
||||
/* Get a pointer to the stream used to open */
|
||||
|
||||
int32_t mz_zip_set_cd_stream(void *handle, int64_t cd_start_pos, void *cd_stream);
|
||||
/* Sets the stream to use for reading the central dir */
|
||||
|
||||
int32_t mz_zip_get_cd_mem_stream(void *handle, void **cd_mem_stream);
|
||||
/* Get a pointer to the stream used to store the central dir in memory */
|
||||
|
||||
int32_t mz_zip_set_number_entry(void *handle, uint64_t number_entry);
|
||||
/* Sets the total number of entries */
|
||||
|
||||
int32_t mz_zip_get_number_entry(void *handle, uint64_t *number_entry);
|
||||
/* Get the total number of entries */
|
||||
|
||||
int32_t mz_zip_set_disk_number_with_cd(void *handle, uint32_t disk_number_with_cd);
|
||||
/* Sets the disk number containing the central directory record */
|
||||
|
||||
int32_t mz_zip_get_disk_number_with_cd(void *handle, uint32_t *disk_number_with_cd);
|
||||
/* Get the disk number containing the central directory record */
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_zip_entry_is_open(void *handle);
|
||||
/* Check to see if entry is open for read/write */
|
||||
|
||||
int32_t mz_zip_entry_read_open(void *handle, uint8_t raw, const char *password);
|
||||
/* Open for reading the current file in the zip file */
|
||||
|
||||
int32_t mz_zip_entry_read(void *handle, void *buf, int32_t len);
|
||||
/* Read bytes from the current file in the zip file */
|
||||
|
||||
int32_t mz_zip_entry_read_close(void *handle, uint32_t *crc32, int64_t *compressed_size,
|
||||
int64_t *uncompressed_size);
|
||||
/* Close the current file for reading and get data descriptor values */
|
||||
|
||||
int32_t mz_zip_entry_write_open(void *handle, const mz_zip_file *file_info,
|
||||
int16_t compress_level, uint8_t raw, const char *password);
|
||||
/* Open for writing the current file in the zip file */
|
||||
|
||||
int32_t mz_zip_entry_write(void *handle, const void *buf, int32_t len);
|
||||
/* Write bytes from the current file in the zip file */
|
||||
|
||||
int32_t mz_zip_entry_write_close(void *handle, uint32_t crc32, int64_t compressed_size,
|
||||
int64_t uncompressed_size);
|
||||
/* Close the current file for writing and set data descriptor values */
|
||||
|
||||
int32_t mz_zip_entry_close_raw(void *handle, int64_t uncompressed_size, uint32_t crc32);
|
||||
/* Close the current file in the zip file where raw is compressed data */
|
||||
|
||||
int32_t mz_zip_entry_close(void *handle);
|
||||
/* Close the current file in the zip file */
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_zip_entry_is_dir(void *handle);
|
||||
/* Checks to see if the entry is a directory */
|
||||
|
||||
int32_t mz_zip_entry_is_symlink(void *handle);
|
||||
/* Checks to see if the entry is a symbolic link */
|
||||
|
||||
int32_t mz_zip_entry_get_info(void *handle, mz_zip_file **file_info);
|
||||
/* Get info about the current file, only valid while current entry is open */
|
||||
|
||||
int32_t mz_zip_entry_get_local_info(void *handle, mz_zip_file **local_file_info);
|
||||
/* Get local info about the current file, only valid while current entry is being read */
|
||||
|
||||
int32_t mz_zip_entry_set_extrafield(void *handle, const uint8_t *extrafield, uint16_t extrafield_size);
|
||||
/* Sets or updates the extra field for the entry to be used before writing cd */
|
||||
|
||||
int64_t mz_zip_get_entry(void *handle);
|
||||
/* Return offset of the current entry in the zip file */
|
||||
|
||||
int32_t mz_zip_goto_entry(void *handle, int64_t cd_pos);
|
||||
/* Go to specified entry in the zip file */
|
||||
|
||||
int32_t mz_zip_goto_first_entry(void *handle);
|
||||
/* Go to the first entry in the zip file */
|
||||
|
||||
int32_t mz_zip_goto_next_entry(void *handle);
|
||||
/* Go to the next entry in the zip file or MZ_END_OF_LIST if reaching the end */
|
||||
|
||||
int32_t mz_zip_locate_entry(void *handle, const char *filename, uint8_t ignore_case);
|
||||
/* Locate the file with the specified name in the zip file or MZ_END_LIST if not found */
|
||||
|
||||
int32_t mz_zip_locate_first_entry(void *handle, void *userdata, mz_zip_locate_entry_cb cb);
|
||||
/* Locate the first matching entry based on a match callback */
|
||||
|
||||
int32_t mz_zip_locate_next_entry(void *handle, void *userdata, mz_zip_locate_entry_cb cb);
|
||||
/* Locate the next matching entry based on a match callback */
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_zip_attrib_is_dir(uint32_t attrib, int32_t version_madeby);
|
||||
/* Checks to see if the attribute is a directory based on platform */
|
||||
|
||||
int32_t mz_zip_attrib_is_symlink(uint32_t attrib, int32_t version_madeby);
|
||||
/* Checks to see if the attribute is a symbolic link based on platform */
|
||||
|
||||
int32_t mz_zip_attrib_convert(uint8_t src_sys, uint32_t src_attrib, uint8_t target_sys,
|
||||
uint32_t *target_attrib);
|
||||
/* Converts file attributes from one host system to another */
|
||||
|
||||
int32_t mz_zip_attrib_posix_to_win32(uint32_t posix_attrib, uint32_t *win32_attrib);
|
||||
/* Converts posix file attributes to win32 file attributes */
|
||||
|
||||
int32_t mz_zip_attrib_win32_to_posix(uint32_t win32_attrib, uint32_t *posix_attrib);
|
||||
/* Converts win32 file attributes to posix file attributes */
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_zip_extrafield_find(void *stream, uint16_t type, uint16_t *length);
|
||||
/* Seeks to extra field by its type and returns its length */
|
||||
|
||||
int32_t mz_zip_extrafield_contains(const uint8_t *extrafield, int32_t extrafield_size,
|
||||
uint16_t type, uint16_t *length);
|
||||
/* Gets whether an extrafield exists and its size */
|
||||
|
||||
int32_t mz_zip_extrafield_read(void *stream, uint16_t *type, uint16_t *length);
|
||||
/* Reads an extrafield header from a stream */
|
||||
|
||||
int32_t mz_zip_extrafield_write(void *stream, uint16_t type, uint16_t length);
|
||||
/* Writes an extrafield header to a stream */
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_zip_dosdate_to_tm(uint64_t dos_date, struct tm *ptm);
|
||||
/* Convert dos date/time format to struct tm */
|
||||
|
||||
time_t mz_zip_dosdate_to_time_t(uint64_t dos_date);
|
||||
/* Convert dos date/time format to time_t */
|
||||
|
||||
int32_t mz_zip_time_t_to_tm(time_t unix_time, struct tm *ptm);
|
||||
/* Convert time_t to time struct */
|
||||
|
||||
uint32_t mz_zip_time_t_to_dos_date(time_t unix_time);
|
||||
/* Convert time_t to dos date/time format */
|
||||
|
||||
uint32_t mz_zip_tm_to_dosdate(const struct tm *ptm);
|
||||
/* Convert struct tm to dos date/time format */
|
||||
|
||||
int32_t mz_zip_ntfs_to_unix_time(uint64_t ntfs_time, time_t *unix_time);
|
||||
/* Convert ntfs time to unix time */
|
||||
|
||||
int32_t mz_zip_unix_to_ntfs_time(time_t unix_time, uint64_t *ntfs_time);
|
||||
/* Convert unix time to ntfs time */
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_zip_path_compare(const char *path1, const char *path2, uint8_t ignore_case);
|
||||
/* Compare two paths without regard to slashes */
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ZIP_H */
|
2103
third-party/ZipArchive/Sources/minizip/mz_zip_rw.c
vendored
Normal file
2103
third-party/ZipArchive/Sources/minizip/mz_zip_rw.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
283
third-party/ZipArchive/Sources/minizip/mz_zip_rw.h
vendored
Normal file
283
third-party/ZipArchive/Sources/minizip/mz_zip_rw.h
vendored
Normal file
@ -0,0 +1,283 @@
|
||||
/* mz_zip_rw.h -- Zip reader/writer
|
||||
Version 2.9.2, February 12, 2020
|
||||
part of the MiniZip project
|
||||
|
||||
Copyright (C) 2010-2020 Nathan Moinvaziri
|
||||
https://github.com/nmoinvaz/minizip
|
||||
|
||||
This program is distributed under the terms of the same license as zlib.
|
||||
See the accompanying LICENSE file for the full text of the license.
|
||||
*/
|
||||
|
||||
#ifndef MZ_ZIP_RW_H
|
||||
#define MZ_ZIP_RW_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
typedef int32_t (*mz_zip_reader_overwrite_cb)(void *handle, void *userdata, mz_zip_file *file_info, const char *path);
|
||||
typedef int32_t (*mz_zip_reader_password_cb)(void *handle, void *userdata, mz_zip_file *file_info, char *password, int32_t max_password);
|
||||
typedef int32_t (*mz_zip_reader_progress_cb)(void *handle, void *userdata, mz_zip_file *file_info, int64_t position);
|
||||
typedef int32_t (*mz_zip_reader_entry_cb)(void *handle, void *userdata, mz_zip_file *file_info, const char *path);
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_zip_reader_is_open(void *handle);
|
||||
/* Checks to see if the zip file is open */
|
||||
|
||||
int32_t mz_zip_reader_open(void *handle, void *stream);
|
||||
/* Opens zip file from stream */
|
||||
|
||||
int32_t mz_zip_reader_open_file(void *handle, const char *path);
|
||||
/* Opens zip file from a file path */
|
||||
|
||||
int32_t mz_zip_reader_open_file_in_memory(void *handle, const char *path);
|
||||
/* Opens zip file from a file path into memory for faster access */
|
||||
|
||||
int32_t mz_zip_reader_open_buffer(void *handle, uint8_t *buf, int32_t len, uint8_t copy);
|
||||
/* Opens zip file from memory buffer */
|
||||
|
||||
int32_t mz_zip_reader_close(void *handle);
|
||||
/* Closes the zip file */
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_zip_reader_unzip_cd(void *handle);
|
||||
/* Unzip the central directory */
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_zip_reader_goto_first_entry(void *handle);
|
||||
/* Goto the first entry in the zip file that matches the pattern */
|
||||
|
||||
int32_t mz_zip_reader_goto_next_entry(void *handle);
|
||||
/* Goto the next entry in the zip file that matches the pattern */
|
||||
|
||||
int32_t mz_zip_reader_locate_entry(void *handle, const char *filename, uint8_t ignore_case);
|
||||
/* Locates an entry by filename */
|
||||
|
||||
int32_t mz_zip_reader_entry_open(void *handle);
|
||||
/* Opens an entry for reading */
|
||||
|
||||
int32_t mz_zip_reader_entry_close(void *handle);
|
||||
/* Closes an entry */
|
||||
|
||||
int32_t mz_zip_reader_entry_read(void *handle, void *buf, int32_t len);
|
||||
/* Reads and entry after being opened */
|
||||
|
||||
int32_t mz_zip_reader_entry_has_sign(void *handle);
|
||||
/* Checks to see if the entry has a signature */
|
||||
|
||||
int32_t mz_zip_reader_entry_sign_verify(void *handle);
|
||||
/* Verifies a signature stored with the entry */
|
||||
|
||||
int32_t mz_zip_reader_entry_get_hash(void *handle, uint16_t algorithm, uint8_t *digest, int32_t digest_size);
|
||||
/* Gets a hash algorithm from the entry's extra field */
|
||||
|
||||
int32_t mz_zip_reader_entry_get_first_hash(void *handle, uint16_t *algorithm, uint16_t *digest_size);
|
||||
/* Gets the most secure hash algorithm from the entry's extra field */
|
||||
|
||||
int32_t mz_zip_reader_entry_get_info(void *handle, mz_zip_file **file_info);
|
||||
/* Gets the current entry file info */
|
||||
|
||||
int32_t mz_zip_reader_entry_is_dir(void *handle);
|
||||
/* Gets the current entry is a directory */
|
||||
|
||||
int32_t mz_zip_reader_entry_save(void *handle, void *stream, mz_stream_write_cb write_cb);
|
||||
/* Save the current entry to a steam */
|
||||
|
||||
int32_t mz_zip_reader_entry_save_process(void *handle, void *stream, mz_stream_write_cb write_cb);
|
||||
/* Saves a portion of the current entry to a stream callback */
|
||||
|
||||
int32_t mz_zip_reader_entry_save_file(void *handle, const char *path);
|
||||
/* Save the current entry to a file */
|
||||
|
||||
int32_t mz_zip_reader_entry_save_buffer(void *handle, void *buf, int32_t len);
|
||||
/* Save the current entry to a memory buffer */
|
||||
|
||||
int32_t mz_zip_reader_entry_save_buffer_length(void *handle);
|
||||
/* Gets the length of the buffer required to save */
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_zip_reader_save_all(void *handle, const char *destination_dir);
|
||||
/* Save all files into a directory */
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
void mz_zip_reader_set_pattern(void *handle, const char *pattern, uint8_t ignore_case);
|
||||
/* Sets the match pattern for entries in the zip file, if null all entries are matched */
|
||||
|
||||
void mz_zip_reader_set_password(void *handle, const char *password);
|
||||
/* Sets the password required for extraction */
|
||||
|
||||
void mz_zip_reader_set_raw(void *handle, uint8_t raw);
|
||||
/* Sets whether or not it should save the entry raw */
|
||||
|
||||
int32_t mz_zip_reader_get_raw(void *handle, uint8_t *raw);
|
||||
/* Gets whether or not it should save the entry raw */
|
||||
|
||||
int32_t mz_zip_reader_get_zip_cd(void *handle, uint8_t *zip_cd);
|
||||
/* Gets whether or not the archive has a zipped central directory */
|
||||
|
||||
int32_t mz_zip_reader_get_comment(void *handle, const char **comment);
|
||||
/* Gets the comment for the central directory */
|
||||
|
||||
void mz_zip_reader_set_encoding(void *handle, int32_t encoding);
|
||||
/* Sets whether or not it should support a special character encoding in zip file names. */
|
||||
|
||||
void mz_zip_reader_set_sign_required(void *handle, uint8_t sign_required);
|
||||
/* Sets whether or not it a signature is required */
|
||||
|
||||
void mz_zip_reader_set_overwrite_cb(void *handle, void *userdata, mz_zip_reader_overwrite_cb cb);
|
||||
/* Callback for what to do when a file is being overwritten */
|
||||
|
||||
void mz_zip_reader_set_password_cb(void *handle, void *userdata, mz_zip_reader_password_cb cb);
|
||||
/* Callback for when a password is required and hasn't been set */
|
||||
|
||||
void mz_zip_reader_set_progress_cb(void *handle, void *userdata, mz_zip_reader_progress_cb cb);
|
||||
/* Callback for extraction progress */
|
||||
|
||||
void mz_zip_reader_set_progress_interval(void *handle, uint32_t milliseconds);
|
||||
/* Let at least milliseconds pass between calls to progress callback */
|
||||
|
||||
void mz_zip_reader_set_entry_cb(void *handle, void *userdata, mz_zip_reader_entry_cb cb);
|
||||
/* Callback for zip file entries */
|
||||
|
||||
int32_t mz_zip_reader_get_zip_handle(void *handle, void **zip_handle);
|
||||
/* Gets the underlying zip instance handle */
|
||||
|
||||
void* mz_zip_reader_create(void **handle);
|
||||
/* Create new instance of zip reader */
|
||||
|
||||
void mz_zip_reader_delete(void **handle);
|
||||
/* Delete instance of zip reader */
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
typedef int32_t (*mz_zip_writer_overwrite_cb)(void *handle, void *userdata, const char *path);
|
||||
typedef int32_t (*mz_zip_writer_password_cb)(void *handle, void *userdata, mz_zip_file *file_info, char *password, int32_t max_password);
|
||||
typedef int32_t (*mz_zip_writer_progress_cb)(void *handle, void *userdata, mz_zip_file *file_info, int64_t position);
|
||||
typedef int32_t (*mz_zip_writer_entry_cb)(void *handle, void *userdata, mz_zip_file *file_info);
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_zip_writer_is_open(void *handle);
|
||||
/* Checks to see if the zip file is open */
|
||||
|
||||
int32_t mz_zip_writer_open(void *handle, void *stream);
|
||||
/* Opens zip file from stream */
|
||||
|
||||
int32_t mz_zip_writer_open_file(void *handle, const char *path, int64_t disk_size, uint8_t append);
|
||||
/* Opens zip file from a file path */
|
||||
|
||||
int32_t mz_zip_writer_open_file_in_memory(void *handle, const char *path);
|
||||
/* Opens zip file from a file path into memory for faster access */
|
||||
|
||||
int32_t mz_zip_writer_close(void *handle);
|
||||
/* Closes the zip file */
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_zip_writer_entry_open(void *handle, mz_zip_file *file_info);
|
||||
/* Opens an entry in the zip file for writing */
|
||||
|
||||
int32_t mz_zip_writer_entry_close(void *handle);
|
||||
/* Closes entry in zip file */
|
||||
|
||||
int32_t mz_zip_writer_entry_write(void *handle, const void *buf, int32_t len);
|
||||
/* Writes data into entry for zip */
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_zip_writer_add(void *handle, void *stream, mz_stream_read_cb read_cb);
|
||||
/* Writes all data to the currently open entry in the zip */
|
||||
|
||||
int32_t mz_zip_writer_add_process(void *handle, void *stream, mz_stream_read_cb read_cb);
|
||||
/* Writes a portion of data to the currently open entry in the zip */
|
||||
|
||||
int32_t mz_zip_writer_add_info(void *handle, void *stream, mz_stream_read_cb read_cb, mz_zip_file *file_info);
|
||||
/* Adds an entry to the zip based on the info */
|
||||
|
||||
int32_t mz_zip_writer_add_buffer(void *handle, void *buf, int32_t len, mz_zip_file *file_info);
|
||||
/* Adds an entry to the zip with a memory buffer */
|
||||
|
||||
int32_t mz_zip_writer_add_file(void *handle, const char *path, const char *filename_in_zip);
|
||||
/* Adds an entry to the zip from a file */
|
||||
|
||||
int32_t mz_zip_writer_add_path(void *handle, const char *path, const char *root_path, uint8_t include_path,
|
||||
uint8_t recursive);
|
||||
/* Enumerates a directory or pattern and adds entries to the zip */
|
||||
|
||||
int32_t mz_zip_writer_copy_from_reader(void *handle, void *reader);
|
||||
/* Adds an entry from a zip reader instance */
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
void mz_zip_writer_set_password(void *handle, const char *password);
|
||||
/* Password to use for encrypting files in the zip */
|
||||
|
||||
void mz_zip_writer_set_comment(void *handle, const char *comment);
|
||||
/* Comment to use for the archive */
|
||||
|
||||
void mz_zip_writer_set_raw(void *handle, uint8_t raw);
|
||||
/* Sets whether or not we should write the entry raw */
|
||||
|
||||
int32_t mz_zip_writer_get_raw(void *handle, uint8_t *raw);
|
||||
/* Gets whether or not we should write the entry raw */
|
||||
|
||||
void mz_zip_writer_set_aes(void *handle, uint8_t aes);
|
||||
/* Use aes encryption when adding files in zip */
|
||||
|
||||
void mz_zip_writer_set_compress_method(void *handle, uint16_t compress_method);
|
||||
/* Sets the compression method when adding files in zip */
|
||||
|
||||
void mz_zip_writer_set_compress_level(void *handle, int16_t compress_level);
|
||||
/* Sets the compression level when adding files in zip */
|
||||
|
||||
void mz_zip_writer_set_follow_links(void *handle, uint8_t follow_links);
|
||||
/* Follow symbolic links when traversing directories and files to add */
|
||||
|
||||
void mz_zip_writer_set_store_links(void *handle, uint8_t store_links);
|
||||
/* Store symbolic links in zip file */
|
||||
|
||||
void mz_zip_writer_set_zip_cd(void *handle, uint8_t zip_cd);
|
||||
/* Sets whether or not central directory should be zipped */
|
||||
|
||||
int32_t mz_zip_writer_set_certificate(void *handle, const char *cert_path, const char *cert_pwd);
|
||||
/* Sets the certificate and timestamp url to use for signing when adding files in zip */
|
||||
|
||||
void mz_zip_writer_set_overwrite_cb(void *handle, void *userdata, mz_zip_writer_overwrite_cb cb);
|
||||
/* Callback for what to do when zip file already exists */
|
||||
|
||||
void mz_zip_writer_set_password_cb(void *handle, void *userdata, mz_zip_writer_password_cb cb);
|
||||
/* Callback for ask if a password is required for adding */
|
||||
|
||||
void mz_zip_writer_set_progress_cb(void *handle, void *userdata, mz_zip_writer_progress_cb cb);
|
||||
/* Callback for compression progress */
|
||||
|
||||
void mz_zip_writer_set_progress_interval(void *handle, uint32_t milliseconds);
|
||||
/* Let at least milliseconds pass between calls to progress callback */
|
||||
|
||||
void mz_zip_writer_set_entry_cb(void *handle, void *userdata, mz_zip_writer_entry_cb cb);
|
||||
/* Callback for zip file entries */
|
||||
|
||||
int32_t mz_zip_writer_get_zip_handle(void *handle, void **zip_handle);
|
||||
/* Gets the underlying zip handle */
|
||||
|
||||
void* mz_zip_writer_create(void **handle);
|
||||
/* Create new instance of zip writer */
|
||||
|
||||
void mz_zip_writer_delete(void **handle);
|
||||
/* Delete instance of zip writer */
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user