From 075ee6cbdbdc5833809511d3c90d3690da7cfcfe Mon Sep 17 00:00:00 2001 From: Roy Marmelstein Date: Wed, 27 Jan 2016 00:33:08 +0100 Subject: [PATCH] Add ability to zip folders and their contents --- Zip.xcodeproj/project.pbxproj | 4 ++ Zip/Zip.swift | 15 ++++--- Zip/ZipUtilities.swift | 85 +++++++++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+), 6 deletions(-) create mode 100644 Zip/ZipUtilities.swift diff --git a/Zip.xcodeproj/project.pbxproj b/Zip.xcodeproj/project.pbxproj index 8baf8ab..61bf745 100644 --- a/Zip.xcodeproj/project.pbxproj +++ b/Zip.xcodeproj/project.pbxproj @@ -36,6 +36,7 @@ 342FC1091C5044DC0023A3C3 /* zip.c in Sources */ = {isa = PBXBuildFile; fileRef = 342FC0ED1C5044DC0023A3C3 /* zip.c */; }; 342FC10A1C5044DC0023A3C3 /* zip.h in Headers */ = {isa = PBXBuildFile; fileRef = 342FC0EE1C5044DC0023A3C3 /* zip.h */; }; 3430F6201C45C805007473A6 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 3430F61F1C45C805007473A6 /* libz.tbd */; }; + 343625BB1C5827DC0023C4C6 /* ZipUtilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 343625BA1C5827DC0023C4C6 /* ZipUtilities.swift */; }; 3443A3F61C4AB8A3004AD173 /* QuickZip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3443A3F51C4AB8A3004AD173 /* QuickZip.swift */; }; 3443A3F91C4AD169004AD173 /* kYkLkPf.gif in Resources */ = {isa = PBXBuildFile; fileRef = 3443A3F81C4AD169004AD173 /* kYkLkPf.gif */; }; 3443A3FB1C4AD16F004AD173 /* 3crBXeO.gif in Resources */ = {isa = PBXBuildFile; fileRef = 3443A3FA1C4AD16F004AD173 /* 3crBXeO.gif */; }; @@ -87,6 +88,7 @@ 342FC0ED1C5044DC0023A3C3 /* zip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zip.c; sourceTree = ""; }; 342FC0EE1C5044DC0023A3C3 /* zip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zip.h; sourceTree = ""; }; 3430F61F1C45C805007473A6 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; + 343625BA1C5827DC0023C4C6 /* ZipUtilities.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ZipUtilities.swift; sourceTree = ""; }; 3443A3F51C4AB8A3004AD173 /* QuickZip.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuickZip.swift; sourceTree = ""; }; 3443A3F81C4AD169004AD173 /* kYkLkPf.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = kYkLkPf.gif; sourceTree = ""; }; 3443A3FA1C4AD16F004AD173 /* 3crBXeO.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = 3crBXeO.gif; sourceTree = ""; }; @@ -189,6 +191,7 @@ 347E3A771C1DFFB500A11FD3 /* Zip.h */, 347E3A791C1DFFB500A11FD3 /* Info.plist */, 347E3AD71C1E04C900A11FD3 /* Zip.swift */, + 343625BA1C5827DC0023C4C6 /* ZipUtilities.swift */, 3443A3F51C4AB8A3004AD173 /* QuickZip.swift */, 3430F61F1C45C805007473A6 /* libz.tbd */, ); @@ -346,6 +349,7 @@ 342FC1001C5044DC0023A3C3 /* pwd2key.c in Sources */, 342FC0F21C5044DC0023A3C3 /* aeskey.c in Sources */, 342FC1091C5044DC0023A3C3 /* zip.c in Sources */, + 343625BB1C5827DC0023C4C6 /* ZipUtilities.swift in Sources */, 342FC0FA1C5044DC0023A3C3 /* fileenc.c in Sources */, 342FC0F81C5044DC0023A3C3 /* entropy.c in Sources */, ); diff --git a/Zip/Zip.swift b/Zip/Zip.swift index 0cedac4..c2a13e0 100644 --- a/Zip/Zip.swift +++ b/Zip/Zip.swift @@ -195,6 +195,9 @@ public class Zip { throw ZipError.FileNotFound } + // Process zip paths + let processedPaths = ZipUtilities().processZipPaths(paths) + // Zip set up let chunkSize: Int = 16384 @@ -202,9 +205,9 @@ public class Zip { var currentPosition: Double = 0.0 var totalSize: Double = 0.0 // Get totalSize for progress handler - for path in paths { + for path in processedPaths { do { - if let filePath = path.path { + if let filePath = path.filePathURL.path { let fileAttributes = try fileManager.attributesOfItemAtPath(filePath) let fileSize = fileAttributes[NSFileSize] as? Double if let fileSize = fileSize { @@ -217,8 +220,8 @@ public class Zip { // Begin Zipping let zip = zipOpen(destinationPath, APPEND_STATUS_CREATE) - for path in paths { - guard let filePath = path.path else { + for path in processedPaths { + guard let filePath = path.filePathURL.path else { throw ZipError.ZipFail } var isDirectory: ObjCBool = false @@ -228,7 +231,7 @@ public class Zip { if input == nil { throw ZipError.ZipFail } - let fileName = path.lastPathComponent + 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) @@ -278,8 +281,8 @@ public class Zip { if let progressHandler = progress{ progressHandler(progress: 1.0) } - } + } \ No newline at end of file diff --git a/Zip/ZipUtilities.swift b/Zip/ZipUtilities.swift new file mode 100644 index 0000000..fcb7f72 --- /dev/null +++ b/Zip/ZipUtilities.swift @@ -0,0 +1,85 @@ +// +// ZipUtilities.swift +// Zip +// +// Created by Roy Marmelstein on 26/01/2016. +// Copyright © 2016 Roy Marmelstein. All rights reserved. +// + +import Foundation + +internal class ZipUtilities { + + // File manager + let fileManager = NSFileManager.defaultManager() + + /** + * ProcessedFilePath struct + */ + internal struct ProcessedFilePath { + let filePathURL: NSURL + let fileName: String? + } + + //MARK: Path processing + + /** + Process zip paths + + - parameter paths: Paths as NSURL. + + - returns: Array of ProcessedFilePath structs. + */ + internal func processZipPaths(paths: [NSURL]) -> [ProcessedFilePath]{ + var processedFilePaths = [ProcessedFilePath]() + for path in paths { + guard let filePath = path.path else { + continue + } + var isDirectory: ObjCBool = false + fileManager.fileExistsAtPath(filePath, isDirectory: &isDirectory) + if !isDirectory { + let processedPath = ProcessedFilePath(filePathURL: path, fileName: path.lastPathComponent) + processedFilePaths.append(processedPath) + } + else { + let directoryContents = expandDirectoryFilePath(path) + processedFilePaths.appendContentsOf(directoryContents) + } + } + return processedFilePaths + } + + + /** + Recursive function to expand directory contents and parse them into ProcessedFilePath structs. + + - parameter directory: Path of folder as NSURL. + + - returns: Array of ProcessedFilePath structs. + */ + internal func expandDirectoryFilePath(directory: NSURL) -> [ProcessedFilePath] { + var processedFilePaths = [ProcessedFilePath]() + if let directoryPath = directory.path, let enumerator = fileManager.enumeratorAtPath(directoryPath) { + while let filePathComponent = enumerator.nextObject() as? String { + let path = directory.URLByAppendingPathComponent(filePathComponent) + guard let filePath = path.path, let directoryName = directory.lastPathComponent else { + continue + } + var isDirectory: ObjCBool = false + fileManager.fileExistsAtPath(filePath, isDirectory: &isDirectory) + if !isDirectory { + let fileName = (directoryName as NSString).stringByAppendingPathComponent(filePathComponent) + let processedPath = ProcessedFilePath(filePathURL: path, fileName: fileName) + processedFilePaths.append(processedPath) + } + else { + let directoryContents = expandDirectoryFilePath(path) + processedFilePaths.appendContentsOf(directoryContents) + } + } + } + return processedFilePaths + } + +} \ No newline at end of file -- 2.26.2