diff --git a/Zip.xcodeproj/project.pbxproj b/Zip.xcodeproj/project.pbxproj index 452beb6619a07f13d498e826e3455a24f215ac74..6fa2a7d0e323f777a4c61ffc3af7f0411c98eb67 100644 --- a/Zip.xcodeproj/project.pbxproj +++ b/Zip.xcodeproj/project.pbxproj @@ -493,7 +493,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Roy Marmelstein"; TargetAttributes = { 343F50FE1C8DAEEC0028C434 = { @@ -504,9 +504,11 @@ }; 347E3A731C1DFFB500A11FD3 = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0800; }; 347E3A7D1C1DFFB500A11FD3 = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0800; }; }; }; @@ -714,6 +716,7 @@ SKIP_INSTALL = YES; SUPPORTED_PLATFORMS = "appletvsimulator appletvos"; SWIFT_INCLUDE_PATHS = "${SRCROOT}/Zip/minizip/**"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; TARGETED_DEVICE_FAMILY = 3; TVOS_DEPLOYMENT_TARGET = 9.0; }; @@ -762,6 +765,7 @@ SDKROOT = macosx; SKIP_INSTALL = YES; SWIFT_INCLUDE_PATHS = "${SRCROOT}/Zip/minizip/**"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; @@ -901,6 +905,7 @@ SKIP_INSTALL = YES; SWIFT_INCLUDE_PATHS = "${SRCROOT}/Zip/minizip/**"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -922,6 +927,8 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_INCLUDE_PATHS = "${SRCROOT}/Zip/minizip/**"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 3.0; }; name = Release; }; @@ -932,6 +939,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.roymarmelstein.ZipTests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -942,6 +950,8 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.roymarmelstein.ZipTests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Zip.xcodeproj/xcshareddata/xcschemes/Zip OSX.xcscheme b/Zip.xcodeproj/xcshareddata/xcschemes/Zip OSX.xcscheme index f802b86d77595215664fcbc48ebf23457a6425c3..dbc1918043198585f5287149f8a64a984f18a549 100644 --- a/Zip.xcodeproj/xcshareddata/xcschemes/Zip OSX.xcscheme +++ b/Zip.xcodeproj/xcshareddata/xcschemes/Zip OSX.xcscheme @@ -1,6 +1,6 @@ NSURL { + public class func quickUnzipFile(_ path: URL) throws -> URL { return try quickUnzipFile(path, progress: nil) } @@ -37,16 +37,20 @@ extension Zip { - returns: NSURL of the destination folder. */ - public class func quickUnzipFile(path: NSURL, progress: ((progress: Double) -> ())?) throws -> NSURL { - let fileManager = NSFileManager.defaultManager() + public class func quickUnzipFile(_ path: URL, progress: ((progress: Double) -> ())?) throws -> URL { + let fileManager = FileManager.default guard let fileExtension = path.pathExtension, let fileName = path.lastPathComponent else { - throw ZipError.UnzipFail + throw ZipError.unzipFail + } + let directoryName = fileName.replacingOccurrences(of: ".\(fileExtension)", with: "") + let documentsUrl = fileManager.urlsForDirectory(.documentDirectory, inDomains: .userDomainMask)[0] as URL + do { + let destinationUrl = try documentsUrl.appendingPathComponent(directoryName, isDirectory: true) + try self.unzipFile(path, destination: destinationUrl, overwrite: true, password: nil, progress: progress) + return destinationUrl + }catch{ + throw(ZipError.unzipFail) } - let directoryName = fileName.stringByReplacingOccurrencesOfString(".\(fileExtension)", withString: "") - let documentsUrl = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0] as NSURL - let destinationUrl = documentsUrl.URLByAppendingPathComponent(directoryName, isDirectory: true) - try self.unzipFile(path, destination: destinationUrl, overwrite: true, password: nil, progress: progress) - return destinationUrl } //MARK: Quick Zip @@ -63,7 +67,7 @@ extension Zip { - returns: NSURL of the destination folder. */ - public class func quickZipFiles(paths: [NSURL], fileName: String) throws -> NSURL { + public class func quickZipFiles(_ paths: [URL], fileName: String) throws -> URL { return try quickZipFiles(paths, fileName: fileName, progress: nil) } @@ -80,13 +84,13 @@ extension Zip { - returns: NSURL of the destination folder. */ - public class func quickZipFiles(paths: [NSURL], fileName: String, progress: ((progress: Double) -> ())?) throws -> NSURL { - let fileManager = NSFileManager.defaultManager() - let documentsUrl = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0] as NSURL - let destinationUrl = documentsUrl.URLByAppendingPathComponent("\(fileName).zip") + public class func quickZipFiles(_ paths: [URL], fileName: String, progress: ((progress: Double) -> ())?) throws -> URL { + let fileManager = FileManager.default + let documentsUrl = fileManager.urlsForDirectory(.documentDirectory, inDomains: .userDomainMask)[0] as URL + let destinationUrl = try! documentsUrl.appendingPathComponent("\(fileName).zip") try self.zipFiles(paths, zipFilePath: destinationUrl, password: nil, progress: progress) return destinationUrl } -} \ No newline at end of file +} diff --git a/Zip/Zip.swift b/Zip/Zip.swift index 4ae40fecf68b50a209a68d8dfb220e14d96f24ae..7f6938964a0cdd4bdecda0aac20dface5c11eab2 100644 --- a/Zip/Zip.swift +++ b/Zip/Zip.swift @@ -10,20 +10,20 @@ import Foundation import minizip /// Zip error type -public enum ZipError: ErrorType { +public enum ZipError: ErrorProtocol { /// File not found - case FileNotFound + case fileNotFound /// Unzip fail - case UnzipFail + case unzipFail /// Zip fail - case ZipFail + case zipFail /// User readable description public var description: String { switch self { - case .FileNotFound: return NSLocalizedString("File not found.", comment: "") - case .UnzipFail: return NSLocalizedString("Failed to unzip file.", comment: "") - case .ZipFail: return NSLocalizedString("Failed to zip file.", comment: "") + case .fileNotFound: return NSLocalizedString("File not found.", comment: "") + case .unzipFail: return NSLocalizedString("Failed to unzip file.", comment: "") + case .zipFail: return NSLocalizedString("Failed to zip file.", comment: "") } } } @@ -62,37 +62,37 @@ public class Zip { - notes: Supports implicit progress composition */ - public class func unzipFile(zipFilePath: NSURL, destination: NSURL, overwrite: Bool, password: String?, progress: ((progress: Double) -> ())?) throws { + public class func unzipFile(_ zipFilePath: URL, destination: URL, overwrite: Bool, password: String?, progress: ((progress: Double) -> ())?) throws { // File manager - let fileManager = NSFileManager.defaultManager() + let fileManager = FileManager.default // Check whether a zip file exists at path. - guard let path = zipFilePath.path where destination.path != nil else { - throw ZipError.FileNotFound + guard let path = zipFilePath.path, destination.path != nil else { + throw ZipError.fileNotFound } - if fileManager.fileExistsAtPath(path) == false || fileExtensionIsInvalid(zipFilePath.pathExtension) { - throw ZipError.FileNotFound + 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(count: Int(bufferSize), repeatedValue: 0) + var buffer = Array(repeating: 0, count: Int(bufferSize)) // Progress handler set up var totalSize: Double = 0.0 var currentPosition: Double = 0.0 - let fileAttributes = try fileManager.attributesOfItemAtPath(path) - if let attributeFileSize = fileAttributes[NSFileSize] as? Double { + let fileAttributes = try fileManager.attributesOfItem(atPath: path) + if let attributeFileSize = fileAttributes[FileAttributeKey.size] as? Double { totalSize += attributeFileSize } - let progressTracker = NSProgress(totalUnitCount: Int64(totalSize)) - progressTracker.cancellable = false - progressTracker.pausable = false - progressTracker.kind = NSProgressKindFile + let progressTracker = Progress(totalUnitCount: Int64(totalSize)) + progressTracker.isCancellable = false + progressTracker.isPausable = false + progressTracker.kind = ProgressKind.file // Begin unzipping let zip = unzOpen64(path) @@ -100,64 +100,66 @@ public class Zip { unzClose(zip) } if unzGoToFirstFile(zip) != UNZ_OK { - throw ZipError.UnzipFail + throw ZipError.unzipFail } repeat { - if let cPassword = password?.cStringUsingEncoding(NSASCIIStringEncoding) { + if let cPassword = password?.cString(using: String.Encoding.ascii) { ret = unzOpenCurrentFilePassword(zip, cPassword) } else { ret = unzOpenCurrentFile(zip); } if ret != UNZ_OK { - throw ZipError.UnzipFail + throw ZipError.unzipFail } var fileInfo = unz_file_info64() - memset(&fileInfo, 0, sizeof(unz_file_info)) + memset(&fileInfo, 0, sizeof(unz_file_info.self)) ret = unzGetCurrentFileInfo64(zip, &fileInfo, nil, 0, nil, 0, nil, 0) if ret != UNZ_OK { unzCloseCurrentFile(zip) - throw ZipError.UnzipFail + throw ZipError.unzipFail } currentPosition += Double(fileInfo.compressed_size) let fileNameSize = Int(fileInfo.size_filename) + 1 - let fileName = UnsafeMutablePointer.alloc(fileNameSize) - if fileName == nil { - throw ZipError.UnzipFail - } + let fileName = UnsafeMutablePointer(allocatingCapacity: fileNameSize) + unzGetCurrentFileInfo64(zip, &fileInfo, fileName, UInt(fileNameSize), nil, 0, nil, 0) fileName[Int(fileInfo.size_filename)] = 0 - guard var pathString = String(CString: fileName, encoding: NSUTF8StringEncoding) else { - throw ZipError.UnzipFail + var pathString = String(cString: fileName) + + guard pathString.characters.count > 0 else { + throw ZipError.unzipFail } + var isDirectory = false let fileInfoSizeFileName = Int(fileInfo.size_filename-1) - if (fileName[fileInfoSizeFileName] == "/".cStringUsingEncoding(NSUTF8StringEncoding)?.first || fileName[fileInfoSizeFileName] == "\\".cStringUsingEncoding(NSUTF8StringEncoding)?.first) { + if (fileName[fileInfoSizeFileName] == "/".cString(using: String.Encoding.utf8)?.first || fileName[fileInfoSizeFileName] == "\\".cString(using: String.Encoding.utf8)?.first) { isDirectory = true; } free(fileName) - if pathString.rangeOfCharacterFromSet(NSCharacterSet(charactersInString: "/\\")) != nil { - pathString = pathString.stringByReplacingOccurrencesOfString("\\", withString: "/") + if pathString.rangeOfCharacter(from: CharacterSet(charactersIn: "/\\")) != nil { + pathString = pathString.replacingOccurrences(of: "\\", with: "/") } - guard let fullPath = destination.URLByAppendingPathComponent(pathString).path else { - throw ZipError.UnzipFail + guard let fullPath = try! destination.appendingPathComponent(pathString).path else { + throw ZipError.unzipFail } - let creationDate = NSDate() - let directoryAttributes = [NSFileCreationDate: creationDate, NSFileModificationDate: creationDate] + let creationDate = Date() + let directoryAttributes = [FileAttributeKey.creationDate.rawValue : creationDate, + FileAttributeKey.modificationDate.rawValue : creationDate] do { if isDirectory { - try fileManager.createDirectoryAtPath(fullPath, withIntermediateDirectories: true, attributes: directoryAttributes) + try fileManager.createDirectory(atPath: fullPath, withIntermediateDirectories: true, attributes: directoryAttributes) } else { - let parentDirectory = (fullPath as NSString).stringByDeletingLastPathComponent - try fileManager.createDirectoryAtPath(parentDirectory, withIntermediateDirectories: true, attributes: directoryAttributes) + let parentDirectory = (fullPath as NSString).deletingLastPathComponent + try fileManager.createDirectory(atPath: parentDirectory, withIntermediateDirectories: true, attributes: directoryAttributes) } } catch {} - if fileManager.fileExistsAtPath(fullPath) && !isDirectory && !overwrite { + if fileManager.fileExists(atPath: fullPath) && !isDirectory && !overwrite { unzCloseCurrentFile(zip) ret = unzGoToNextFile(zip) } - var filePointer: UnsafeMutablePointer + var filePointer: UnsafeMutablePointer? filePointer = fopen(fullPath, "wb") while filePointer != nil { let readBytes = unzReadCurrentFile(zip, &buffer, bufferSize) @@ -171,7 +173,7 @@ public class Zip { fclose(filePointer) crc_ret = unzCloseCurrentFile(zip) if crc_ret == UNZ_CRCERROR { - throw ZipError.UnzipFail + throw ZipError.unzipFail } ret = unzGoToNextFile(zip) @@ -207,14 +209,14 @@ public class Zip { - notes: Supports implicit progress composition */ - public class func zipFiles(paths: [NSURL], zipFilePath: NSURL, password: String?, progress: ((progress: Double) -> ())?) throws { + public class func zipFiles(_ paths: [URL], zipFilePath: URL, password: String?, progress: ((progress: Double) -> ())?) throws { // File manager - let fileManager = NSFileManager.defaultManager() + let fileManager = FileManager.default // Check whether a zip file exists at path. guard let destinationPath = zipFilePath.path else { - throw ZipError.FileNotFound + throw ZipError.fileNotFound } // Process zip paths @@ -230,8 +232,8 @@ public class Zip { for path in processedPaths { do { let filePath = path.filePath() - let fileAttributes = try fileManager.attributesOfItemAtPath(filePath) - let fileSize = fileAttributes[NSFileSize] as? Double + let fileAttributes = try fileManager.attributesOfItem(atPath: filePath) + let fileSize = fileAttributes[FileAttributeKey.size] as? Double if let fileSize = fileSize { totalSize += fileSize } @@ -239,36 +241,36 @@ public class Zip { catch {} } - let progressTracker = NSProgress(totalUnitCount: Int64(totalSize)) - progressTracker.cancellable = false - progressTracker.pausable = false - progressTracker.kind = NSProgressKindFile + 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 { let filePath = path.filePath() var isDirectory: ObjCBool = false - fileManager.fileExistsAtPath(filePath, isDirectory: &isDirectory) + fileManager.fileExists(atPath: filePath, isDirectory: &isDirectory) if !isDirectory { let input = fopen(filePath, "r") if input == nil { - throw ZipError.ZipFail + throw ZipError.zipFail } let fileName = path.fileName var zipInfo: zip_fileinfo = zip_fileinfo(tmz_date: tm_zip(tm_sec: 0, tm_min: 0, tm_hour: 0, tm_mday: 0, tm_mon: 0, tm_year: 0), dosDate: 0, internal_fa: 0, external_fa: 0) do { - let fileAttributes = try fileManager.attributesOfItemAtPath(filePath) - if let fileDate = fileAttributes[NSFileModificationDate] as? NSDate { - let components = NSCalendar.currentCalendar().components([.Year, .Month, .Day, .Hour, .Minute, .Second], fromDate: fileDate) - zipInfo.tmz_date.tm_sec = UInt32(components.second) - zipInfo.tmz_date.tm_min = UInt32(components.minute) - zipInfo.tmz_date.tm_hour = UInt32(components.hour) - zipInfo.tmz_date.tm_mday = UInt32(components.day) - zipInfo.tmz_date.tm_mon = UInt32(components.month) - 1 - zipInfo.tmz_date.tm_year = UInt32(components.year) + let fileAttributes = try fileManager.attributesOfItem(atPath: filePath) + if let fileDate = fileAttributes[FileAttributeKey.modificationDate] as? Date { + let components = Calendar.current.components([.year, .month, .day, .hour, .minute, .second], from: fileDate) + zipInfo.tmz_date.tm_sec = UInt32(components.second!) + zipInfo.tmz_date.tm_min = UInt32(components.minute!) + zipInfo.tmz_date.tm_hour = UInt32(components.hour!) + zipInfo.tmz_date.tm_mday = UInt32(components.day!) + zipInfo.tmz_date.tm_mon = UInt32(components.month!) - 1 + zipInfo.tmz_date.tm_year = UInt32(components.year!) } - if let fileSize = fileAttributes[NSFileSize] as? Double { + if let fileSize = fileAttributes[FileAttributeKey.size] as? Double { currentPosition += fileSize } } @@ -281,7 +283,7 @@ public class Zip { zipOpenNewFileInZip3(zip, fileName, &zipInfo, nil, 0, nil, 0, nil,Z_DEFLATED, Z_DEFAULT_COMPRESSION, 0, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, nil, 0) } else { - throw ZipError.ZipFail + throw ZipError.zipFail } var length: Int = 0 while (feof(input) == 0) { @@ -318,7 +320,7 @@ public class Zip { - returns: false if the extension is a valid file extension, otherwise true. */ - internal class func fileExtensionIsInvalid(fileExtension: String?) -> Bool { + internal class func fileExtensionIsInvalid(_ fileExtension: String?) -> Bool { guard let fileExtension = fileExtension else { return true } @@ -330,7 +332,7 @@ public class Zip { - parameter fileExtension: A file extension. */ - public class func addCustomFileExtension(fileExtension: String) { + public class func addCustomFileExtension(_ fileExtension: String) { customFileExtensions.insert(fileExtension) } @@ -339,7 +341,7 @@ public class Zip { - parameter fileExtension: A file extension. */ - public class func removeCustomFileExtension(fileExtension: String) { + public class func removeCustomFileExtension(_ fileExtension: String) { customFileExtensions.remove(fileExtension) } @@ -350,7 +352,7 @@ public class Zip { - returns: true if the extension valid, otherwise false. */ - public class func isValidFileExtension(fileExtension: String) -> Bool { + public class func isValidFileExtension(_ fileExtension: String) -> Bool { let validFileExtensions: Set = customFileExtensions.union(["zip", "cbz"]) diff --git a/Zip/ZipUtilities.swift b/Zip/ZipUtilities.swift index dd9b0d9885de70d3296f6e6c28fe54c173fca779..bed157429f1d6d6b08cadd73d251b07207f167b0 100644 --- a/Zip/ZipUtilities.swift +++ b/Zip/ZipUtilities.swift @@ -11,13 +11,13 @@ import Foundation internal class ZipUtilities { // File manager - let fileManager = NSFileManager.defaultManager() + let fileManager = FileManager.default /** * ProcessedFilePath struct */ internal struct ProcessedFilePath { - let filePathURL: NSURL + let filePathURL: URL let fileName: String? func filePath() -> String { @@ -39,21 +39,21 @@ internal class ZipUtilities { - returns: Array of ProcessedFilePath structs. */ - internal func processZipPaths(paths: [NSURL]) -> [ProcessedFilePath]{ + internal func processZipPaths(_ paths: [URL]) -> [ProcessedFilePath]{ var processedFilePaths = [ProcessedFilePath]() for path in paths { guard let filePath = path.path else { continue } var isDirectory: ObjCBool = false - fileManager.fileExistsAtPath(filePath, isDirectory: &isDirectory) + fileManager.fileExists(atPath: filePath, isDirectory: &isDirectory) if !isDirectory { let processedPath = ProcessedFilePath(filePathURL: path, fileName: path.lastPathComponent) processedFilePaths.append(processedPath) } else { let directoryContents = expandDirectoryFilePath(path) - processedFilePaths.appendContentsOf(directoryContents) + processedFilePaths.append(contentsOf: directoryContents) } } return processedFilePaths @@ -67,28 +67,28 @@ internal class ZipUtilities { - returns: Array of ProcessedFilePath structs. */ - internal func expandDirectoryFilePath(directory: NSURL) -> [ProcessedFilePath] { + internal func expandDirectoryFilePath(_ directory: URL) -> [ProcessedFilePath] { var processedFilePaths = [ProcessedFilePath]() - if let directoryPath = directory.path, let enumerator = fileManager.enumeratorAtPath(directoryPath) { + if let directoryPath = directory.path, let enumerator = fileManager.enumerator(atPath: directoryPath) { while let filePathComponent = enumerator.nextObject() as? String { - let path = directory.URLByAppendingPathComponent(filePathComponent) + let path = try! directory.appendingPathComponent(filePathComponent) guard let filePath = path.path, let directoryName = directory.lastPathComponent else { continue } var isDirectory: ObjCBool = false - fileManager.fileExistsAtPath(filePath, isDirectory: &isDirectory) + fileManager.fileExists(atPath: filePath, isDirectory: &isDirectory) if !isDirectory { - let fileName = (directoryName as NSString).stringByAppendingPathComponent(filePathComponent) + let fileName = (directoryName as NSString).appendingPathComponent(filePathComponent) let processedPath = ProcessedFilePath(filePathURL: path, fileName: fileName) processedFilePaths.append(processedPath) } else { let directoryContents = expandDirectoryFilePath(path) - processedFilePaths.appendContentsOf(directoryContents) + processedFilePaths.append(contentsOf: directoryContents) } } } return processedFilePaths } -} \ No newline at end of file +}