diff --git a/.swift-version b/.swift-version index 7d5c902e777905446c67de7e52a945b88fd2038c..bf77d549685a9e09678fbbda05a071b312cf2de3 100644 --- a/.swift-version +++ b/.swift-version @@ -1 +1 @@ -4.1 +4.2 diff --git a/Zip/Zip.swift b/Zip/Zip.swift index 0616484a7d361d0718b4bccf66c3b021f80e5df8..a8b2aa8f25566c4eabb752a755bcd7321f52349e 100644 --- a/Zip/Zip.swift +++ b/Zip/Zip.swift @@ -17,7 +17,7 @@ public enum ZipError: Error { case unzipFail /// Zip fail case zipFail - + /// User readable description public var description: String { switch self { @@ -64,56 +64,56 @@ public struct ArchiveFile { /// Zip class public class Zip { - + /** Set of vaild file extensions */ internal static var customFileExtensions: Set = [] - + // MARK: Lifecycle - + /** Init - + - returns: Zip object */ public init () { } - + // MARK: Unzip - + /** Unzip file - + - parameter zipFilePath: Local file path of zipped file. NSURL. - parameter destination: Local file path to unzip to. NSURL. - parameter overwrite: Overwrite bool. - parameter password: Optional password if file is protected. - parameter progress: A progress closure called after unzipping each file in the archive. Double value betweem 0 and 1. - + - throws: Error if unzipping fails or if fail is not found. Can be printed with a description variable. - + - notes: Supports implicit progress composition */ - + public class func unzipFile(_ zipFilePath: URL, destination: URL, overwrite: Bool, password: String?, progress: ((_ progress: Double) -> ())? = nil, fileOutputHandler: ((_ unzippedFile: URL) -> Void)? = nil) throws { - + // File manager let fileManager = FileManager.default - + // Check whether a zip file exists at path. let path = zipFilePath.path - + if fileManager.fileExists(atPath: path) == false || fileExtensionIsInvalid(zipFilePath.pathExtension) { throw ZipError.fileNotFound } - + // Unzip set up var ret: Int32 = 0 var crc_ret: Int32 = 0 let bufferSize: UInt32 = 4096 var buffer = Array(repeating: 0, count: Int(bufferSize)) - + // Progress handler set up var totalSize: Double = 0.0 var currentPosition: Double = 0.0 @@ -121,12 +121,12 @@ public class Zip { if let attributeFileSize = fileAttributes[FileAttributeKey.size] as? Double { totalSize += attributeFileSize } - + let progressTracker = Progress(totalUnitCount: Int64(totalSize)) progressTracker.isCancellable = false progressTracker.isPausable = false progressTracker.kind = ProgressKind.file - + // Begin unzipping let zip = unzOpen64(path) defer { @@ -153,24 +153,25 @@ public class Zip { throw ZipError.unzipFail } currentPosition += Double(fileInfo.compressed_size) - let fileNameSize = Int(fileInfo.size_filename) + 1 + fileInfo.size_filename = 10240 + let fileNameSize = 10240 // Int(fileInfo.size_filename) + 1 //let fileName = UnsafeMutablePointer(allocatingCapacity: fileNameSize) let fileName = UnsafeMutablePointer.allocate(capacity: fileNameSize) unzGetCurrentFileInfo64(zip, &fileInfo, fileName, UInt(fileNameSize), nil, 0, nil, 0) - fileName[Int(fileInfo.size_filename)] = 0 + //fileName[Int(fileInfo.size_filename)] = 0 var pathString = String(cString: fileName) - + guard pathString.count > 0 else { throw ZipError.unzipFail } - var isDirectory = false - let fileInfoSizeFileName = Int(fileInfo.size_filename-1) - if (fileName[fileInfoSizeFileName] == "/".cString(using: String.Encoding.utf8)?.first || fileName[fileInfoSizeFileName] == "\\".cString(using: String.Encoding.utf8)?.first) { - isDirectory = true; - } + // var isDirectory = false + // let fileInfoSizeFileName = Int(fileInfo.size_filename-1) + // if (fileName[fileInfoSizeFileName] == "/".cString(using: String.Encoding.utf8)?.first || fileName[fileInfoSizeFileName] == "\\".cString(using: String.Encoding.utf8)?.first) { + // isDirectory = true; + // } free(fileName) if pathString.rangeOfCharacter(from: CharacterSet(charactersIn: "/\\")) != nil { pathString = pathString.replacingOccurrences(of: "\\", with: "/") @@ -184,15 +185,15 @@ public class Zip { FileAttributeKey.modificationDate : creationDate] do { - if isDirectory { - try fileManager.createDirectory(atPath: fullPath, withIntermediateDirectories: true, attributes: directoryAttributes) - } - else { + // if isDirectory { + // try fileManager.createDirectory(atPath: fullPath, withIntermediateDirectories: true, attributes: directoryAttributes) + // } + // else { let parentDirectory = (fullPath as NSString).deletingLastPathComponent try fileManager.createDirectory(atPath: parentDirectory, withIntermediateDirectories: true, attributes: directoryAttributes) - } + // } } catch {} - if fileManager.fileExists(atPath: fullPath) && !isDirectory && !overwrite { + if fileManager.fileExists(atPath: fullPath) && !overwrite { // !isDirectory && !overwrite { unzCloseCurrentFile(zip) ret = unzGoToNextFile(zip) } @@ -237,61 +238,61 @@ public class Zip { } ret = unzGoToNextFile(zip) - + // Update progress handler if let progressHandler = progress{ progressHandler((currentPosition/totalSize)) } - + if let fileHandler = fileOutputHandler, let encodedString = fullPath.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed), let fileUrl = URL(string: encodedString) { fileHandler(fileUrl) } - + progressTracker.completedUnitCount = Int64(currentPosition) - + } while (ret == UNZ_OK && ret != UNZ_END_OF_LIST_OF_FILE) - + // Completed. Update progress handler. if let progressHandler = progress{ progressHandler(1.0) } - + progressTracker.completedUnitCount = Int64(totalSize) - + } - + // MARK: Zip - - + + /** Zip files. - + - parameter paths: Array of NSURL filepaths. - parameter zipFilePath: Destination NSURL, should lead to a .zip filepath. - parameter password: Password string. Optional. - parameter compression: Compression strategy - parameter progress: A progress closure called after unzipping each file in the archive. Double value betweem 0 and 1. - + - throws: Error if zipping fails. - + - notes: Supports implicit progress composition */ public class func zipFiles(paths: [URL], zipFilePath: URL, password: String?, compression: ZipCompression = .DefaultCompression, progress: ((_ progress: Double) -> ())?) throws { - + // File manager let fileManager = FileManager.default - + // Check whether a zip file exists at path. let destinationPath = zipFilePath.path - + // Process zip paths let processedPaths = ZipUtilities().processZipPaths(paths) - + // Zip set up let chunkSize: Int = 16384 - + // Progress handler set up var currentPosition: Double = 0.0 var totalSize: Double = 0.0 @@ -307,12 +308,12 @@ public class Zip { } catch {} } - + let progressTracker = Progress(totalUnitCount: Int64(totalSize)) progressTracker.isCancellable = false progressTracker.isPausable = false progressTracker.kind = ProgressKind.file - + // Begin Zipping let zip = zipOpen(destinationPath, APPEND_STATUS_CREATE) for path in processedPaths { @@ -357,44 +358,44 @@ public class Zip { length = fread(buffer, 1, chunkSize, input) zipWriteInFileInZip(zip, buffer, UInt32(length)) } - + // Update progress handler if let progressHandler = progress{ progressHandler((currentPosition/totalSize)) } - + progressTracker.completedUnitCount = Int64(currentPosition) - + zipCloseFileInZip(zip) free(buffer) fclose(input) } } zipClose(zip, nil) - + // Completed. Update progress handler. if let progressHandler = progress{ progressHandler(1.0) } - + progressTracker.completedUnitCount = Int64(totalSize) } /** Zip data in memory. - + - parameter archiveFiles:Array of Archive Files. - parameter zipFilePath: Destination NSURL, should lead to a .zip filepath. - parameter password: Password string. Optional. - parameter compression: Compression strategy - parameter progress: A progress closure called after unzipping each file in the archive. Double value betweem 0 and 1. - + - throws: Error if zipping fails. - + - notes: Supports implicit progress composition */ public class func zipData(archiveFiles:[ArchiveFile], zipFilePath:URL, password: String?, compression: ZipCompression = .DefaultCompression, progress: ((_ progress: Double) -> ())?) throws { - + let destinationPath = zipFilePath.path // Progress handler set up @@ -475,51 +476,51 @@ public class Zip { progressTracker.completedUnitCount = Int64(totalSize) } - + /** Check if file extension is invalid. - + - parameter fileExtension: A file extension. - + - returns: false if the extension is a valid file extension, otherwise true. */ internal class func fileExtensionIsInvalid(_ fileExtension: String?) -> Bool { - + guard let fileExtension = fileExtension else { return true } - + return !isValidFileExtension(fileExtension) } - + /** Add a file extension to the set of custom file extensions - + - parameter fileExtension: A file extension. */ public class func addCustomFileExtension(_ fileExtension: String) { customFileExtensions.insert(fileExtension) } - + /** Remove a file extension from the set of custom file extensions - + - parameter fileExtension: A file extension. */ public class func removeCustomFileExtension(_ fileExtension: String) { customFileExtensions.remove(fileExtension) } - + /** Check if a specific file extension is valid - + - parameter fileExtension: A file extension. - + - returns: true if the extension valid, otherwise false. */ public class func isValidFileExtension(_ fileExtension: String) -> Bool { - + let validFileExtensions: Set = customFileExtensions.union(["zip", "cbz"]) - + return validFileExtensions.contains(fileExtension) } - + }