From fd89a04c8e184ebd3438ac669ea9dcc628e44e3b Mon Sep 17 00:00:00 2001 From: Amir Abbas Date: Sat, 24 Feb 2018 23:41:45 +0330 Subject: [PATCH] Fixed FTP/SSL issue, Fixed error descriptions for HTTP and FTP - Changed thumbnail and properties method signature to support progress --- Sources/DropboxFileProvider.swift | 10 +++++---- Sources/DropboxHelper.swift | 2 +- Sources/ExtendedLocalFileProvider.swift | 6 ++++-- Sources/FPSStreamTask.swift | 28 ++++++++++++++----------- Sources/FTPHelper.swift | 18 +++++++++------- Sources/FileProvider.swift | 14 ++++++++----- Sources/OneDriveFileProvider.swift | 8 ++++--- Sources/OneDriveHelper.swift | 2 +- Sources/RemoteSession.swift | 10 ++++----- Sources/WebDAVFileProvider.swift | 12 ++++++----- 10 files changed, 65 insertions(+), 45 deletions(-) diff --git a/Sources/DropboxFileProvider.swift b/Sources/DropboxFileProvider.swift index 975053f..c9733a2 100644 --- a/Sources/DropboxFileProvider.swift +++ b/Sources/DropboxFileProvider.swift @@ -268,7 +268,7 @@ open class DropboxFileProvider: HTTPFileProvider, FileProviderSharing { } else { errorDesc = data.flatMap({ String(data: $0, encoding: .utf8) }) } - return FileProviderDropboxError(code: code, path: path ?? "", errorDescription: errorDesc) + return FileProviderDropboxError(code: code, path: path ?? "", serverDescription: errorDesc) } override var maxUploadSimpleSupported: Int64 { @@ -417,7 +417,7 @@ extension DropboxFileProvider: ExtendedFileProvider { } /// Default value for dimension is 64x64, according to Dropbox documentation - open func thumbnailOfFile(path: String, dimension: CGSize?, completionHandler: @escaping ((_ image: ImageClass?, _ error: Error?) -> Void)) { + open func thumbnailOfFile(path: String, dimension: CGSize?, completionHandler: @escaping ((_ image: ImageClass?, _ error: Error?) -> Void)) -> Progress? { let url: URL let thumbAPI: Bool switch (path as NSString).pathExtension.lowercased() { @@ -432,7 +432,7 @@ extension DropboxFileProvider: ExtendedFileProvider { url = URL(string: "files/get_preview", relativeTo: contentURL)! thumbAPI = false default: - return + return nil } var request = URLRequest(url: url) request.setValue(authentication: credential, with: .oAuth2) @@ -469,9 +469,10 @@ extension DropboxFileProvider: ExtendedFileProvider { completionHandler(image, error) }) task.resume() + return nil } - open func propertiesOfFile(path: String, completionHandler: @escaping ((_ propertiesDictionary: [String : Any], _ keys: [String], _ error: Error?) -> Void)) { + open func propertiesOfFile(path: String, completionHandler: @escaping ((_ propertiesDictionary: [String : Any], _ keys: [String], _ error: Error?) -> Void)) -> Progress? { let url = URL(string: "files/get_metadata", relativeTo: apiURL)! var request = URLRequest(url: url) request.httpMethod = "POST" @@ -493,5 +494,6 @@ extension DropboxFileProvider: ExtendedFileProvider { completionHandler(dic, keys, serverError ?? error) }) task.resume() + return nil } } diff --git a/Sources/DropboxHelper.swift b/Sources/DropboxHelper.swift index 457f0e1..407a089 100644 --- a/Sources/DropboxHelper.swift +++ b/Sources/DropboxHelper.swift @@ -12,7 +12,7 @@ import Foundation public struct FileProviderDropboxError: FileProviderHTTPError { public let code: FileProviderHTTPErrorCode public let path: String - public let errorDescription: String? + public let serverDescription: String? } /// Containts path, url and attributes of a Dropbox file or resource. diff --git a/Sources/ExtendedLocalFileProvider.swift b/Sources/ExtendedLocalFileProvider.swift index 7860be9..5fa049e 100644 --- a/Sources/ExtendedLocalFileProvider.swift +++ b/Sources/ExtendedLocalFileProvider.swift @@ -54,7 +54,7 @@ extension LocalFileProvider: ExtendedFileProvider { } } - open func thumbnailOfFile(path: String, dimension: CGSize? = nil, completionHandler: @escaping ((_ image: ImageClass?, _ error: Error?) -> Void)) { + open func thumbnailOfFile(path: String, dimension: CGSize? = nil, completionHandler: @escaping ((_ image: ImageClass?, _ error: Error?) -> Void)) -> Progress? { let dimension = dimension ?? CGSize(width: 64, height: 64) (dispatch_queue).async { var thumbnailImage: ImageClass? = nil @@ -84,9 +84,10 @@ extension LocalFileProvider: ExtendedFileProvider { completionHandler(scaledImage, nil) } } + return nil } - open func propertiesOfFile(path: String, completionHandler: @escaping ((_ propertiesDictionary: [String: Any], _ keys: [String], _ error: Error?) -> Void)) { + open func propertiesOfFile(path: String, completionHandler: @escaping ((_ propertiesDictionary: [String: Any], _ keys: [String], _ error: Error?) -> Void)) -> Progress? { (dispatch_queue).async { let fileExt = (path as NSString).pathExtension.lowercased() var getter: ((_ fileURL: URL) -> (prop: [String: Any], keys: [String]))? @@ -117,6 +118,7 @@ extension LocalFileProvider: ExtendedFileProvider { completionHandler(dic, keys, nil) } + return nil } } diff --git a/Sources/FPSStreamTask.swift b/Sources/FPSStreamTask.swift index e0f20af..8ad4890 100644 --- a/Sources/FPSStreamTask.swift +++ b/Sources/FPSStreamTask.swift @@ -418,13 +418,19 @@ public class FileProviderStreamTask: URLSessionTask, StreamDelegate { return } + if isSecure { + inputStream.setProperty(securityLevel.rawValue, forKey: .socketSecurityLevelKey) + outputStream.setProperty(securityLevel.rawValue, forKey: .socketSecurityLevelKey) + } else { + inputStream.setProperty(StreamSocketSecurityLevel.none.rawValue, forKey: .socketSecurityLevelKey) + outputStream.setProperty(StreamSocketSecurityLevel.none.rawValue, forKey: .socketSecurityLevelKey) + } + inputStream.delegate = self outputStream.delegate = self - operation_queue.addOperation { - inputStream.schedule(in: RunLoop.main, forMode: .defaultRunLoopMode) - outputStream.schedule(in: RunLoop.main, forMode: .defaultRunLoopMode) - } + inputStream.schedule(in: RunLoop.main, forMode: .defaultRunLoopMode) + outputStream.schedule(in: RunLoop.main, forMode: .defaultRunLoopMode) inputStream.open() outputStream.open() @@ -629,6 +635,9 @@ public class FileProviderStreamTask: URLSessionTask, StreamDelegate { } } + fileprivate var isSecure = false + + public var securityLevel: StreamSocketSecurityLevel = .tlSv1 /** * Completes any enqueued reads and writes, and establishes a secure connection. * @@ -643,10 +652,7 @@ public class FileProviderStreamTask: URLSessionTask, StreamDelegate { } } - operation_queue.addOperation { - self.inputStream!.setProperty(StreamSocketSecurityLevel.negotiatedSSL.rawValue, forKey: .socketSecurityLevelKey) - self.outputStream!.setProperty(StreamSocketSecurityLevel.negotiatedSSL.rawValue, forKey: .socketSecurityLevelKey) - } + isSecure = true } /** @@ -659,10 +665,8 @@ public class FileProviderStreamTask: URLSessionTask, StreamDelegate { return } } - operation_queue.addOperation { - self.inputStream!.setProperty(StreamSocketSecurityLevel.none.rawValue, forKey: .socketSecurityLevelKey) - self.outputStream!.setProperty(StreamSocketSecurityLevel.none.rawValue, forKey: .socketSecurityLevelKey) - } + + isSecure = false } open func stream(_ aStream: Stream, handle eventCode: Stream.Event) { diff --git a/Sources/FTPHelper.swift b/Sources/FTPHelper.swift index e49f37b..efa4538 100644 --- a/Sources/FTPHelper.swift +++ b/Sources/FTPHelper.swift @@ -936,18 +936,18 @@ internal extension FTPFileProvider { } /// Contains error code and description returned by FTP/S provider. -public struct FileProviderFTPError: Error { +public struct FileProviderFTPError: LocalizedError { /// HTTP status code returned for error by server. public let code: Int /// Path of file/folder casued that error public let path: String /// Contents returned by server as error description - public let errorDescription: String? + public let serverDescription: String? - init(code: Int, path: String, errorDescription: String?) { + init(code: Int, path: String, serverDescription: String?) { self.code = code self.path = path - self.errorDescription = errorDescription + self.serverDescription = serverDescription } init(message response: String, path: String = "") { @@ -962,12 +962,16 @@ public struct FileProviderFTPError: Error { self.path = path if code > 0 { #if swift(>=4.0) - self.errorDescription = message[startIndex...].trimmingCharacters(in: .whitespacesAndNewlines) + self.serverDescription = message[startIndex...].trimmingCharacters(in: .whitespacesAndNewlines) #else - self.errorDescription = message.substring(from: startIndex).trimmingCharacters(in: .whitespacesAndNewlines) + self.serverDescription = message.substring(from: startIndex).trimmingCharacters(in: .whitespacesAndNewlines) #endif } else { - self.errorDescription = message + self.serverDescription = message } } + + public var errorDescription: String? { + return serverDescription + } } diff --git a/Sources/FileProvider.swift b/Sources/FileProvider.swift index 2e8c590..8b8ed60 100644 --- a/Sources/FileProvider.swift +++ b/Sources/FileProvider.swift @@ -815,7 +815,8 @@ public protocol ExtendedFileProvider: FileProviderBasic { - image: `NSImage`/`UIImage` object contains preview. - error: `Error` returned by system. */ - func thumbnailOfFile(path: String, completionHandler: @escaping (_ image: ImageClass?, _ error: Error?) -> Void) + @discardableResult + func thumbnailOfFile(path: String, completionHandler: @escaping (_ image: ImageClass?, _ error: Error?) -> Void) -> Progress? /** Generates and returns a thumbnail preview of document asynchronously. The defualt dimension of returned image is different @@ -831,7 +832,8 @@ public protocol ExtendedFileProvider: FileProviderBasic { - image: `NSImage`/`UIImage` object contains preview. - error: `Error` returned by system. */ - func thumbnailOfFile(path: String, dimension: CGSize?, completionHandler: @escaping (_ image: ImageClass?, _ error: Error?) -> Void) + @discardableResult + func thumbnailOfFile(path: String, dimension: CGSize?, completionHandler: @escaping (_ image: ImageClass?, _ error: Error?) -> Void) -> Progress? /** Fetching properties of file like dimensions, duration, etc. It's variant depending on file type. @@ -847,12 +849,14 @@ public protocol ExtendedFileProvider: FileProviderBasic { - keys: An `Array` contains ordering of keys. - error: Error returned by system. */ - func propertiesOfFile(path: String, completionHandler: @escaping (_ propertiesDictionary: [String: Any], _ keys: [String], _ error: Error?) -> Void) + @discardableResult + func propertiesOfFile(path: String, completionHandler: @escaping (_ propertiesDictionary: [String: Any], _ keys: [String], _ error: Error?) -> Void) -> Progress? } extension ExtendedFileProvider { - public func thumbnailOfFile(path: String, completionHandler: @escaping ((_ image: ImageClass?, _ error: Error?) -> Void)) { - self.thumbnailOfFile(path: path, dimension: nil, completionHandler: completionHandler) + @discardableResult + public func thumbnailOfFile(path: String, completionHandler: @escaping ((_ image: ImageClass?, _ error: Error?) -> Void)) -> Progress? { + return self.thumbnailOfFile(path: path, dimension: nil, completionHandler: completionHandler) } internal static func convertToImage(pdfData: Data?, page: Int = 1) -> ImageClass? { diff --git a/Sources/OneDriveFileProvider.swift b/Sources/OneDriveFileProvider.swift index 716758b..96d57ce 100644 --- a/Sources/OneDriveFileProvider.swift +++ b/Sources/OneDriveFileProvider.swift @@ -510,7 +510,7 @@ open class OneDriveFileProvider: HTTPFileProvider, FileProviderSharing { } else { errorDesc = data.flatMap({ String(data: $0, encoding: .utf8) }) } - return FileProviderOneDriveError(code: code, path: path ?? "", errorDescription: errorDesc) + return FileProviderOneDriveError(code: code, path: path ?? "", serverDescription: errorDesc) } override var maxUploadSimpleSupported: Int64 { @@ -574,7 +574,7 @@ extension OneDriveFileProvider: ExtendedFileProvider { } } - open func thumbnailOfFile(path: String, dimension: CGSize?, completionHandler: @escaping ((_ image: ImageClass?, _ error: Error?) -> Void)) { + open func thumbnailOfFile(path: String, dimension: CGSize?, completionHandler: @escaping ((_ image: ImageClass?, _ error: Error?) -> Void)) -> Progress? { let url: URL if let dimension = dimension { url = self.url(of: path, modifier: "thumbnails/0/=c\(dimension.width)x\(dimension.height)/content") @@ -595,9 +595,10 @@ extension OneDriveFileProvider: ExtendedFileProvider { completionHandler(image, error) }) task.resume() + return nil } - open func propertiesOfFile(path: String, completionHandler: @escaping ((_ propertiesDictionary: [String : Any], _ keys: [String], _ error: Error?) -> Void)) { + open func propertiesOfFile(path: String, completionHandler: @escaping ((_ propertiesDictionary: [String : Any], _ keys: [String], _ error: Error?) -> Void)) -> Progress? { var request = URLRequest(url: url(of: path)) request.httpMethod = "GET" request.setValue(authentication: credential, with: .oAuth2) @@ -615,5 +616,6 @@ extension OneDriveFileProvider: ExtendedFileProvider { completionHandler(dic, keys, serverError ?? error) }) task.resume() + return nil } } diff --git a/Sources/OneDriveHelper.swift b/Sources/OneDriveHelper.swift index bdbaa7f..843c796 100644 --- a/Sources/OneDriveHelper.swift +++ b/Sources/OneDriveHelper.swift @@ -12,7 +12,7 @@ import Foundation public struct FileProviderOneDriveError: FileProviderHTTPError { public let code: FileProviderHTTPErrorCode public let path: String - public let errorDescription: String? + public let serverDescription: String? } /// Containts path, url and attributes of a OneDrive file or resource. diff --git a/Sources/RemoteSession.swift b/Sources/RemoteSession.swift index d1542d4..39f9655 100755 --- a/Sources/RemoteSession.swift +++ b/Sources/RemoteSession.swift @@ -10,7 +10,7 @@ import Foundation /// A protocol defines properties for errors returned by HTTP/S based providers. /// Including Dropbox, OneDrive and WebDAV. -public protocol FileProviderHTTPError: Error, CustomStringConvertible { +public protocol FileProviderHTTPError: LocalizedError, CustomStringConvertible { /// HTTP status codes as an enum. typealias Code = FileProviderHTTPErrorCode /// HTTP status code returned for error by server. @@ -18,16 +18,16 @@ public protocol FileProviderHTTPError: Error, CustomStringConvertible { /// Path of file/folder casued that error var path: String { get } /// Contents returned by server as error description - var errorDescription: String? { get } + var serverDescription: String? { get } } extension FileProviderHTTPError { public var description: String { - return code.description + return "Status \(code.rawValue): \(code.description)" } - public var localizedDescription: String { - return description + public var errorDescription: String? { + return "Status \(code.rawValue): \(code.description)" } } diff --git a/Sources/WebDAVFileProvider.swift b/Sources/WebDAVFileProvider.swift index 74ca3a4..316b599 100644 --- a/Sources/WebDAVFileProvider.swift +++ b/Sources/WebDAVFileProvider.swift @@ -360,7 +360,7 @@ open class WebDAVFileProvider: HTTPFileProvider, FileProviderSharing { } override func serverError(with code: FileProviderHTTPErrorCode, path: String?, data: Data?) -> FileProviderHTTPError { - return FileProviderWebDavError(code: code, path: path ?? "", errorDescription: data.flatMap({ String(data: $0, encoding: .utf8) }), url: self.url(of: path ?? "")) + return FileProviderWebDavError(code: code, path: path ?? "", serverDescription: data.flatMap({ String(data: $0, encoding: .utf8) }), url: self.url(of: path ?? "")) } override func multiStatusHandler(source: String, data: Data, completionHandler: SimpleCompletionHandler) { @@ -397,12 +397,12 @@ extension WebDAVFileProvider: ExtendedFileProvider { return supportedExt.contains((path as NSString).pathExtension) } - open func thumbnailOfFile(path: String, dimension: CGSize?, completionHandler: @escaping ((ImageClass?, Error?) -> Void)) { + open func thumbnailOfFile(path: String, dimension: CGSize?, completionHandler: @escaping ((ImageClass?, Error?) -> Void)) -> Progress? { guard self.baseURL?.host?.contains("dav.yandex.") ?? false else { dispatch_queue.async { completionHandler(nil, self.urlError(path, code: .resourceUnavailable)) } - return + return nil } let dimension = dimension ?? CGSize(width: 64, height: 64) @@ -421,16 +421,18 @@ extension WebDAVFileProvider: ExtendedFileProvider { completionHandler(data.flatMap({ ImageClass(data: $0) }), nil) }) task.resume() + return nil } open func propertiesOfFileSupported(path: String) -> Bool { return false } - open func propertiesOfFile(path: String, completionHandler: @escaping (([String : Any], [String], Error?) -> Void)) { + open func propertiesOfFile(path: String, completionHandler: @escaping (([String : Any], [String], Error?) -> Void)) -> Progress? { dispatch_queue.async { completionHandler([:], [], self.urlError(path, code: .resourceUnavailable)) } + return nil } } @@ -629,7 +631,7 @@ public final class WebDavFileObject: FileObject { public struct FileProviderWebDavError: FileProviderHTTPError { public let code: FileProviderHTTPErrorCode public let path: String - public let errorDescription: String? + public let serverDescription: String? /// URL of resource caused error. public let url: URL }