Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dca5dddbfd | |||
| 6764c23f1b | |||
| 955a86372b | |||
| 32a20fbc49 | |||
| 921ba19afa | |||
| 8625b0464c | |||
| 1bf9d1eadd | |||
| cbf774ba9e |
+10
@@ -0,0 +1,10 @@
|
||||
language: objective-c
|
||||
osx_image: xcode7.3
|
||||
script:
|
||||
- set pipefail
|
||||
- xcodebuild -project FileProvider.xcodeproj -scheme "FileProvider OSX" -sdk macosx | xcpretty
|
||||
- xcodebuild -project FileProvider.xcodeproj -scheme "FileProvider iOS" -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO | xcpretty
|
||||
- xcodebuild -project FileProvider.xcodeproj -scheme "FileProvider tvOS" -sdk appletvsimulator ONLY_ACTIVE_ARCH=NO | xcpretty
|
||||
- pod lib lint --quick
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
@@ -7,6 +7,9 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
7902C0861D61B56D00564440 /* SessionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7902C0851D61B56D00564440 /* SessionDelegate.swift */; };
|
||||
7902C0871D61B67100564440 /* SessionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7902C0851D61B56D00564440 /* SessionDelegate.swift */; };
|
||||
7902C0881D61B67100564440 /* SessionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7902C0851D61B56D00564440 /* SessionDelegate.swift */; };
|
||||
794C21FE1D58912A00EC49B8 /* DropboxHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 794C21FD1D58912A00EC49B8 /* DropboxHelper.swift */; };
|
||||
794C21FF1D58912A00EC49B8 /* DropboxHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 794C21FD1D58912A00EC49B8 /* DropboxHelper.swift */; };
|
||||
794C22001D58912A00EC49B8 /* DropboxHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 794C21FD1D58912A00EC49B8 /* DropboxHelper.swift */; };
|
||||
@@ -76,6 +79,7 @@
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
7902C0851D61B56D00564440 /* SessionDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SessionDelegate.swift; sourceTree = "<group>"; };
|
||||
794C21FD1D58912A00EC49B8 /* DropboxHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DropboxHelper.swift; sourceTree = "<group>"; };
|
||||
794C22091D5893F800EC49B8 /* SMB2Notification.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SMB2Notification.swift; sourceTree = "<group>"; };
|
||||
794C220D1D591A4B00EC49B8 /* SMB2QueryTypes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SMB2QueryTypes.swift; sourceTree = "<group>"; };
|
||||
@@ -171,6 +175,7 @@
|
||||
799396941D48C02300086753 /* FileProvider.h */,
|
||||
799396951D48C02300086753 /* FileProvider.swift */,
|
||||
799396961D48C02300086753 /* LocalFileProvider.swift */,
|
||||
7902C0851D61B56D00564440 /* SessionDelegate.swift */,
|
||||
799396971D48C02300086753 /* SMBClient.swift */,
|
||||
799396981D48C02300086753 /* SMBFileProvider.swift */,
|
||||
794C22111D599FBE00EC49B8 /* FPSStreamTask.swift */,
|
||||
@@ -359,6 +364,7 @@
|
||||
799396BC1D48C02300086753 /* CIFSTypes.swift in Sources */,
|
||||
794C220A1D5893F800EC49B8 /* SMB2Notification.swift in Sources */,
|
||||
799396D11D48C02300086753 /* SMB2SetInfo.swift in Sources */,
|
||||
7902C0861D61B56D00564440 /* SessionDelegate.swift in Sources */,
|
||||
799396A71D48C02300086753 /* AEXML.swift in Sources */,
|
||||
799396CE1D48C02300086753 /* SMB2Session.swift in Sources */,
|
||||
799396E01D48C02300086753 /* WebDAVFileProvider.swift in Sources */,
|
||||
@@ -388,6 +394,7 @@
|
||||
799396BD1D48C02300086753 /* CIFSTypes.swift in Sources */,
|
||||
794C220B1D5893F800EC49B8 /* SMB2Notification.swift in Sources */,
|
||||
799396D21D48C02300086753 /* SMB2SetInfo.swift in Sources */,
|
||||
7902C0871D61B67100564440 /* SessionDelegate.swift in Sources */,
|
||||
799396A81D48C02300086753 /* AEXML.swift in Sources */,
|
||||
799396CF1D48C02300086753 /* SMB2Session.swift in Sources */,
|
||||
799396E11D48C02300086753 /* WebDAVFileProvider.swift in Sources */,
|
||||
@@ -417,6 +424,7 @@
|
||||
799396BE1D48C02300086753 /* CIFSTypes.swift in Sources */,
|
||||
794C220C1D5893F800EC49B8 /* SMB2Notification.swift in Sources */,
|
||||
799396D31D48C02300086753 /* SMB2SetInfo.swift in Sources */,
|
||||
7902C0881D61B67100564440 /* SessionDelegate.swift in Sources */,
|
||||
799396A91D48C02300086753 /* AEXML.swift in Sources */,
|
||||
799396D01D48C02300086753 /* SMB2Session.swift in Sources */,
|
||||
799396E21D48C02300086753 /* WebDAVFileProvider.swift in Sources */,
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "FileProvider"
|
||||
)
|
||||
@@ -4,12 +4,15 @@
|
||||
|
||||
[![Swift Version][swift-image]][swift-url]
|
||||
[![License][license-image]][license-url]
|
||||
[]()
|
||||
[](https://img.shields.io/cocoapods/v/FileProvider.svg)
|
||||
[]()
|
||||
|
||||
[![Build Status][travis-image]][travis-url]
|
||||
[](https://cocoapods.org/pods/FileProvider)
|
||||
[![codebeat badge][codebeat-image]][codebeat-url]
|
||||
|
||||
<!---
|
||||
[![Build Status][travis-image]][travis-url]
|
||||
|
||||
[](https://codecov.io/gh/amosavian/FileProvider)
|
||||
[](https://github.com/Carthage/Carthage)
|
||||
--->
|
||||
|
||||
@@ -22,10 +25,10 @@ Local and WebDAV providers are fully tested and can be used in production enviro
|
||||
## Features
|
||||
|
||||
- [x] **LocalFileProvider** a wrapper around `NSFileManager` with some additions like searching and reading a portion of file.
|
||||
- [x] **WebDAVFileProvider** WebDAV protocol is defacto file transmission protocol standard, replaced FTP.
|
||||
- [x] **WebDAVFileProvider** WebDAV protocol is defacto file transmission standard, replaced FTP.
|
||||
- [x] **DropboxFileProvider** A wrapper around Dropbox Web API. For now it has limitation in uploading files up to 150MB.
|
||||
- [ ] **SMBFileProvider** SMB2/3 introduced in 2006, which is a file and printer sharing protocol originated from Microsoft Windows and now is replacing AFP protocol on MacOS. I implemented data types and some basic functions but *main interface is not implemented yet!*. SMB1/CIFS is depericated and very tricky to be implemented
|
||||
- [ ] **FTPFileProvider** while depericated in 1990s, it's still in use on some Web hosts.
|
||||
- [ ] **FTPFileProvider** while deprecated in 1990s, it's still in use on some Web hosts.
|
||||
- [ ] **AmazonS3FileProvider**
|
||||
|
||||
## Requirements
|
||||
@@ -277,17 +280,13 @@ Amir-Abbas Mousavian – [@amosavian](https://twitter.com/amosavian)
|
||||
|
||||
Distributed under the MIT license. See `LICENSE` for more information.
|
||||
|
||||
[https://github.com/yourname/github-link](https://github.com/dbader/)
|
||||
[https://github.com/amosavian/](https://github.com/amosavian/)
|
||||
|
||||
[swift-image]:https://img.shields.io/badge/swift-2.2%2C%202.3-green.svg
|
||||
[swift-image]:https://img.shields.io/badge/Swift-2.2%2C%202.3-green.svg
|
||||
[swift-url]: https://swift.org/
|
||||
[license-image]: https://img.shields.io/badge/License-MIT-blue.svg
|
||||
[license-url]: LICENSE
|
||||
[codebeat-image]: https://codebeat.co/badges/7b359f48-78eb-4647-ab22-56262a827517
|
||||
[codebeat-url]: https://codebeat.co/projects/github-com-amosavian-fileprovider
|
||||
|
||||
|
||||
<!---
|
||||
[travis-image]: https://img.shields.io/travis/dbader/node-datadog-metrics/master.svg?style=flat-square
|
||||
[travis-url]: https://travis-ci.org/dbader/node-datadog-metrics
|
||||
--->
|
||||
[travis-image]: https://img.shields.io/travis/amosavian/FileProvider/master.svg
|
||||
[travis-url]: https://travis-ci.org/amosavian/FileProvider
|
||||
@@ -26,11 +26,13 @@ public class DropboxFileProvider: NSObject, FileProviderBasic {
|
||||
public let credential: NSURLCredential?
|
||||
|
||||
private var _session: NSURLSession?
|
||||
private var sessionDelegate: SessionDelegate?
|
||||
internal var session: NSURLSession {
|
||||
if _session == nil {
|
||||
self.sessionDelegate = SessionDelegate(fileProvider: self, credential: credential)
|
||||
let queue = NSOperationQueue()
|
||||
//queue.underlyingQueue = dispatch_queue
|
||||
_session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration(), delegate: self, delegateQueue: queue)
|
||||
_session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration(), delegate: sessionDelegate, delegateQueue: queue)
|
||||
}
|
||||
return _session!
|
||||
}
|
||||
@@ -67,7 +69,7 @@ public class DropboxFileProvider: NSObject, FileProviderBasic {
|
||||
}
|
||||
let code = FileProviderHTTPErrorCode(rawValue: response.statusCode)
|
||||
let dbError: FileProviderDropboxError? = code != nil ? FileProviderDropboxError(code: code!, path: path, errorDescription: String(data: data ?? NSData(), encoding: NSUTF8StringEncoding)) : nil
|
||||
if let data = data, let jsonStr = String(data: data, encoding: NSUTF8StringEncoding), let json = self.jsonToDictionary(jsonStr), let file = self.mapToFileObject(json) {
|
||||
if let data = data, let jsonStr = String(data: data, encoding: NSUTF8StringEncoding), let json = jsonToDictionary(jsonStr), let file = self.mapToFileObject(json) {
|
||||
completionHandler(attributes: file, error: dbError)
|
||||
return
|
||||
}
|
||||
@@ -85,7 +87,7 @@ public class DropboxFileProvider: NSObject, FileProviderBasic {
|
||||
request.HTTPMethod = "POST"
|
||||
request.setValue("Bearer \(credential?.password ?? "")", forHTTPHeaderField: "Authorization")
|
||||
let task = session.dataTaskWithRequest(request) { (data, response, error) in
|
||||
if let data = data, let jsonStr = String(data: data, encoding: NSUTF8StringEncoding), let json = self.jsonToDictionary(jsonStr) {
|
||||
if let data = data, let jsonStr = String(data: data, encoding: NSUTF8StringEncoding), let json = jsonToDictionary(jsonStr) {
|
||||
let totalSize = ((json["allocation"] as? NSDictionary)?["allocated"] as? NSNumber)?.longLongValue ?? -1
|
||||
let usedSize = (json["used"] as? NSNumber)?.longLongValue ?? 0
|
||||
completionHandler(total: totalSize, used: usedSize)
|
||||
@@ -177,7 +179,7 @@ extension DropboxFileProvider: FileProviderOperations {
|
||||
completionHandler?(error: error)
|
||||
return
|
||||
}
|
||||
upload_simple(toPath, data: data, overwrite: true, operation: .Copy(source: localFile.absoluteString, destination: toPath), completionHandler: completionHandler)
|
||||
upload_simple(toPath, data: data, overwrite: true, operation: .Copy(source: localFile.uw_absoluteString, destination: toPath), completionHandler: completionHandler)
|
||||
}
|
||||
|
||||
public func copyPathToLocalFile(path: String, toLocalURL destURL: NSURL, completionHandler: SimpleCompletionHandler) {
|
||||
@@ -202,7 +204,7 @@ extension DropboxFileProvider: FileProviderOperations {
|
||||
completionHandler?(error: e)
|
||||
}
|
||||
})
|
||||
task.taskDescription = self.dictionaryToJSON(["type": "Copy", "source": path, "dest": destURL.uw_absoluteString])
|
||||
task.taskDescription = dictionaryToJSON(["type": "Copy", "source": path, "dest": destURL.uw_absoluteString])
|
||||
task.resume()
|
||||
}
|
||||
}
|
||||
@@ -309,7 +311,7 @@ extension DropboxFileProvider: ExtendedFileProvider {
|
||||
request.setValue(dictionaryToJSON(requestDictionary), forHTTPHeaderField: "Dropbox-API-Arg")
|
||||
self.session.dataTaskWithRequest(request) { (data, response, error) in
|
||||
var image: ImageClass? = nil
|
||||
if let r = response as? NSHTTPURLResponse, let result = r.allHeaderFields["Dropbox-API-Result"] as? String, let jsonResult = self.jsonToDictionary(result) {
|
||||
if let r = response as? NSHTTPURLResponse, let result = r.allHeaderFields["Dropbox-API-Result"] as? String, let jsonResult = jsonToDictionary(result) {
|
||||
if jsonResult["error"] != nil {
|
||||
completionHandler(image: nil, error: self.throwError(path, code: NSURLError.CannotDecodeRawData))
|
||||
}
|
||||
@@ -327,52 +329,3 @@ extension DropboxFileProvider: ExtendedFileProvider {
|
||||
}
|
||||
|
||||
extension DropboxFileProvider: FileProvider {}
|
||||
|
||||
// MARK: URLSession delegate
|
||||
extension DropboxFileProvider: NSURLSessionDataDelegate, NSURLSessionDownloadDelegate {
|
||||
public func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) {
|
||||
return
|
||||
}
|
||||
|
||||
public func URLSession(session: NSURLSession, task: NSURLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
|
||||
guard let desc = task.taskDescription, let json = jsonToDictionary(desc) else {
|
||||
return
|
||||
}
|
||||
guard let type = json["type"] as? String, let source = json["source"] as? String else {
|
||||
return
|
||||
}
|
||||
let dest = json["dest"] as? String
|
||||
let op : FileOperation
|
||||
switch type {
|
||||
case "Create":
|
||||
op = .Create(path: source)
|
||||
case "Copy":
|
||||
guard let dest = dest else { return }
|
||||
op = .Copy(source: source, destination: dest)
|
||||
case "Move":
|
||||
guard let dest = dest else { return }
|
||||
op = .Move(source: source, destination: dest)
|
||||
case "Modify":
|
||||
op = .Modify(path: source)
|
||||
case "Remove":
|
||||
op = .Remove(path: source)
|
||||
case "Link":
|
||||
guard let dest = dest else { return }
|
||||
op = .Link(link: source, target: dest)
|
||||
default:
|
||||
return
|
||||
}
|
||||
|
||||
let progress = Float(totalBytesSent) / Float(totalBytesExpectedToSend)
|
||||
|
||||
self.delegate?.fileproviderProgress(self, operation: op, progress: progress)
|
||||
}
|
||||
|
||||
public func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
|
||||
guard let desc = downloadTask.taskDescription, let json = jsonToDictionary(desc), let source = json["source"] as? String, dest = json["dest"] as? String else {
|
||||
return
|
||||
}
|
||||
|
||||
self.delegate?.fileproviderProgress(self, operation: .Copy(source: source, destination: dest), progress: Float(totalBytesWritten) / Float(totalBytesExpectedToWrite))
|
||||
}
|
||||
}
|
||||
@@ -23,14 +23,17 @@ public final class DropboxFileObject: FileObject {
|
||||
public let id: String?
|
||||
public let rev: String?
|
||||
|
||||
// codebeat:disable[ARITY]
|
||||
public init(name: String, path: String, size: Int64 = -1, serverTime: NSDate? = nil, modifiedDate: NSDate? = nil, fileType: FileType = .Regular, isHidden: Bool = false, isReadOnly: Bool = false, id: String? = nil, rev: String? = nil) {
|
||||
self.serverTime = serverTime
|
||||
self.id = id
|
||||
self.rev = rev
|
||||
super.init(absoluteURL: NSURL(string: path), name: name, path: path, size: size, createdDate: nil, modifiedDate: modifiedDate, fileType: fileType, isHidden: isHidden, isReadOnly: isReadOnly)
|
||||
}
|
||||
// codebeat:enable[ARITY]
|
||||
}
|
||||
|
||||
// codebeat:disable[ARITY]
|
||||
internal extension DropboxFileProvider {
|
||||
func list(path: String, cursor: String? = nil, prevContents: [DropboxFileObject] = [], recursive: Bool = false, completionHandler: ((contents: [FileObject], cursor: String?, error: ErrorType?) -> Void)) {
|
||||
var requestDictionary = [String: AnyObject]()
|
||||
@@ -54,7 +57,7 @@ internal extension DropboxFileProvider {
|
||||
responseError = FileProviderDropboxError(code: rCode, path: path, errorDescription: String(data: data ?? NSData(), encoding: NSUTF8StringEncoding))
|
||||
}
|
||||
if let data = data, let jsonStr = String(data: data, encoding: NSUTF8StringEncoding) {
|
||||
let json = self.jsonToDictionary(jsonStr)
|
||||
let json = jsonToDictionary(jsonStr)
|
||||
if let entries = json?["entries"] as? [AnyObject] where entries.count > 0 {
|
||||
var files = prevContents
|
||||
for entry in entries {
|
||||
@@ -118,7 +121,7 @@ internal extension DropboxFileProvider {
|
||||
default:
|
||||
break
|
||||
}
|
||||
task.taskDescription = self.dictionaryToJSON(dic)
|
||||
task.taskDescription = dictionaryToJSON(dic)
|
||||
task.resume()
|
||||
}
|
||||
|
||||
@@ -139,7 +142,7 @@ internal extension DropboxFileProvider {
|
||||
responseError = FileProviderDropboxError(code: rCode, path: startPath, errorDescription: String(data: data ?? NSData(), encoding: NSUTF8StringEncoding))
|
||||
}
|
||||
if let data = data, let jsonStr = String(data: data, encoding: NSUTF8StringEncoding) {
|
||||
let json = self.jsonToDictionary(jsonStr)
|
||||
let json = jsonToDictionary(jsonStr)
|
||||
if let entries = json?["matches"] as? [AnyObject] where entries.count > 0 {
|
||||
for entry in entries {
|
||||
if let entry = entry as? [String: AnyObject], let file = self.mapToFileObject(entry) {
|
||||
@@ -161,10 +164,11 @@ internal extension DropboxFileProvider {
|
||||
task.resume()
|
||||
}
|
||||
}
|
||||
// codebeat:enable[ARITY]
|
||||
|
||||
internal extension DropboxFileProvider {
|
||||
func mapToFileObject(jsonStr: String) -> DropboxFileObject? {
|
||||
guard let json = self.jsonToDictionary(jsonStr) else { return nil }
|
||||
guard let json = jsonToDictionary(jsonStr) else { return nil }
|
||||
return self.mapToFileObject(json)
|
||||
}
|
||||
|
||||
|
||||
+17
-17
@@ -260,23 +260,6 @@ extension FileProviderBasic {
|
||||
//self.init()
|
||||
return nil
|
||||
}
|
||||
|
||||
internal func jsonToDictionary(jsonString: String) -> [String: AnyObject]? {
|
||||
guard let data = jsonString.dataUsingEncoding(NSUTF8StringEncoding) else {
|
||||
return nil
|
||||
}
|
||||
if let dic = try? NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions()) as? [String: AnyObject] {
|
||||
return dic
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
internal func dictionaryToJSON(dictionary: [String: AnyObject]) -> String? {
|
||||
if let data = try? NSJSONSerialization.dataWithJSONObject(dictionary, options: NSJSONWritingOptions()) {
|
||||
return String(data: data, encoding: NSUTF8StringEncoding)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -369,3 +352,20 @@ internal extension NSURL {
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
internal func jsonToDictionary(jsonString: String) -> [String: AnyObject]? {
|
||||
guard let data = jsonString.dataUsingEncoding(NSUTF8StringEncoding) else {
|
||||
return nil
|
||||
}
|
||||
if let dic = try? NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions()) as? [String: AnyObject] {
|
||||
return dic
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
internal func dictionaryToJSON(dictionary: [String: AnyObject]) -> String? {
|
||||
if let data = try? NSJSONSerialization.dataWithJSONObject(dictionary, options: NSJSONWritingOptions()) {
|
||||
return String(data: data, encoding: NSUTF8StringEncoding)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -10,11 +10,12 @@ import Foundation
|
||||
|
||||
public final class LocalFileObject: FileObject {
|
||||
public let allocatedSize: Int64
|
||||
|
||||
public init(absoluteURL: NSURL, name: String, path: String, size: Int64, allocatedSize: Int64, createdDate: NSDate?, modifiedDate: NSDate?, fileType: FileType, isHidden: Bool, isReadOnly: Bool) {
|
||||
// codebeat:disable[ARITY]
|
||||
public init(absoluteURL: NSURL, name: String, path: String, size: Int64 = -1, allocatedSize: Int64 = 0, createdDate: NSDate? = nil, modifiedDate: NSDate? = nil, fileType: FileType = .Regular, isHidden: Bool = false, isReadOnly: Bool = false) {
|
||||
self.allocatedSize = allocatedSize
|
||||
super.init(absoluteURL: absoluteURL, name: name, path: path, size: size, createdDate: createdDate, modifiedDate: modifiedDate, fileType: fileType, isHidden: isHidden, isReadOnly: isReadOnly)
|
||||
}
|
||||
// codebeat:enable[ARITY]
|
||||
}
|
||||
|
||||
public class LocalFileProvider: FileProvider, FileProviderMonitor {
|
||||
|
||||
@@ -75,7 +75,7 @@ struct SMB1 {
|
||||
}
|
||||
}
|
||||
|
||||
init(command: Command, ntStatus: UInt32 = 0, flags: Flags, flags2: Flags2 = [.LONG_NAMES, .ERR_STATUS, .UNICODE], securityKey: UInt32 = 0, securityCID: UInt16 = 0, securitySequenceNumber: UInt16 = 0, treeId: UInt16, pid: UInt32, userId: UInt16, multiplexId: UInt16) {
|
||||
init(command: Command, treeId: UInt16, pid: UInt32, userId: UInt16, multiplexId: UInt16, flags: Flags, flags2: Flags2 = [.LONG_NAMES, .ERR_STATUS, .UNICODE], ntStatus: UInt32 = 0, securityKey: UInt32 = 0, securityCID: UInt16 = 0, securitySequenceNumber: UInt16 = 0) {
|
||||
self.protocolID = Header.protocolConst
|
||||
self._command = command.rawValue
|
||||
_status = (UInt8(ntStatus & 0xff), UInt8(ntStatus >> 8 & 0xff), UInt8(ntStatus >> 16 & 0xff), UInt8(ntStatus >> 24 & 0xff))
|
||||
|
||||
@@ -45,6 +45,7 @@ struct SMB2 {
|
||||
let sessionId: UInt64
|
||||
let signature: (UInt64, UInt64)
|
||||
|
||||
// codebeat:disable[ARITY]
|
||||
init(command: Command, status: NTStatus = .SUCCESS, creditCharge: UInt16 = 0, creditRequestResponse: UInt16, flags: Flags = [], nextCommand: UInt32 = 0, messageId: UInt64, treeId: UInt32, sessionId: UInt64, signature: (UInt64, UInt64) = (0, 0)) {
|
||||
self.protocolID = self.dynamicType.protocolConst
|
||||
self.size = 64
|
||||
@@ -76,6 +77,7 @@ struct SMB2 {
|
||||
self.sessionId = sessionId
|
||||
self.signature = signature
|
||||
}
|
||||
// codebeat:enable[ARITY]
|
||||
}
|
||||
|
||||
struct Flags: OptionSetType {
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
//
|
||||
// SessionDelegate.swift
|
||||
// FileProvider
|
||||
//
|
||||
// Created by Amir Abbas Mousavian.
|
||||
// Copyright © 2016 Mousavian. Distributed under MIT license.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class SessionDelegate: NSObject, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate {
|
||||
|
||||
weak var fileProvider: FileProvider?
|
||||
var credential: NSURLCredential?
|
||||
|
||||
var finishDownloadHandler: ((session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL: NSURL) -> Void)?
|
||||
var didSendDataHandler: ((session: NSURLSession, task: NSURLSessionTask, bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) -> Void)?
|
||||
var didReceivedData: ((session: NSURLSession, downloadTask: NSURLSessionDownloadTask, bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) -> Void)?
|
||||
|
||||
init(fileProvider: FileProvider, credential: NSURLCredential?) {
|
||||
self.fileProvider = fileProvider
|
||||
self.credential = credential
|
||||
}
|
||||
|
||||
// codebeat:disable[ARITY]
|
||||
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) {
|
||||
self.finishDownloadHandler?(session: session, downloadTask: downloadTask, didFinishDownloadingToURL: location)
|
||||
return
|
||||
}
|
||||
|
||||
func URLSession(session: NSURLSession, task: NSURLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
|
||||
self.didSendDataHandler?(session: session, task: task, bytesSent: bytesSent, totalBytesSent: totalBytesSent, totalBytesExpectedToSend: totalBytesExpectedToSend)
|
||||
|
||||
guard let desc = task.taskDescription, let json = jsonToDictionary(desc) else {
|
||||
return
|
||||
}
|
||||
guard let type = json["type"] as? String, let source = json["source"] as? String else {
|
||||
return
|
||||
}
|
||||
let dest = json["dest"] as? String
|
||||
let op : FileOperation
|
||||
switch type {
|
||||
case "Create":
|
||||
op = .Create(path: source)
|
||||
case "Copy":
|
||||
guard let dest = dest else { return }
|
||||
op = .Copy(source: source, destination: dest)
|
||||
case "Move":
|
||||
guard let dest = dest else { return }
|
||||
op = .Move(source: source, destination: dest)
|
||||
case "Modify":
|
||||
op = .Modify(path: source)
|
||||
case "Remove":
|
||||
op = .Remove(path: source)
|
||||
case "Link":
|
||||
guard let dest = dest else { return }
|
||||
op = .Link(link: source, target: dest)
|
||||
default:
|
||||
return
|
||||
}
|
||||
|
||||
let progress = Float(totalBytesSent) / Float(totalBytesExpectedToSend)
|
||||
|
||||
fileProvider?.delegate?.fileproviderProgress(fileProvider!, operation: op, progress: progress)
|
||||
}
|
||||
|
||||
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
|
||||
self.didReceivedData?(session: session, downloadTask: downloadTask, bytesWritten: bytesWritten, totalBytesWritten: totalBytesWritten, totalBytesExpectedToWrite: totalBytesExpectedToWrite)
|
||||
|
||||
guard let desc = downloadTask.taskDescription, let json = jsonToDictionary(desc), let source = json["source"] as? String, dest = json["dest"] as? String else {
|
||||
return
|
||||
}
|
||||
|
||||
fileProvider?.delegate?.fileproviderProgress(fileProvider!, operation: .Copy(source: source, destination: dest), progress: Float(totalBytesWritten) / Float(totalBytesExpectedToWrite))
|
||||
}
|
||||
|
||||
func URLSession(session: NSURLSession, task: NSURLSessionTask, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
|
||||
let deposition: NSURLSessionAuthChallengeDisposition = credential != nil ? .UseCredential : .PerformDefaultHandling
|
||||
completionHandler(deposition, credential)
|
||||
}
|
||||
|
||||
func URLSession(session: NSURLSession, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
|
||||
let deposition: NSURLSessionAuthChallengeDisposition = credential != nil ? .UseCredential : .PerformDefaultHandling
|
||||
completionHandler(deposition, credential)
|
||||
}
|
||||
}
|
||||
|
||||
public enum FileProviderHTTPErrorCode: Int {
|
||||
case Continue = 100
|
||||
case SwitchingProtocols = 101
|
||||
case Processing = 102
|
||||
case OK = 200
|
||||
case Created = 201
|
||||
case Accepted = 202
|
||||
case NonAuthoritativeInformation = 203
|
||||
case NoContent = 204
|
||||
case ResetContent = 205
|
||||
case PartialContent = 206
|
||||
case MultiStatus = 207
|
||||
case AlreadyReported = 208
|
||||
case IMUsed = 226
|
||||
case MultipleChoices = 300
|
||||
case MovedPermanently = 301
|
||||
case Found = 302
|
||||
case SeeOther = 303
|
||||
case NotModified = 304
|
||||
case UseProxy = 305
|
||||
case SwitchProxy = 306
|
||||
case TemporaryRedirect = 307
|
||||
case PermanentRedirect = 308
|
||||
case BadRequest = 400
|
||||
case Unauthorized = 401
|
||||
case PaymentRequired = 402
|
||||
case Forbidden = 403
|
||||
case NotFound = 404
|
||||
case MethodNotAllowed = 405
|
||||
case NotAcceptable = 406
|
||||
case ProxyAuthenticationRequired = 407
|
||||
case RequestTimeout = 408
|
||||
case Conflict = 409
|
||||
case Gone = 410
|
||||
case LengthRequired = 411
|
||||
case PreconditionFailed = 412
|
||||
case PayloadTooLarge = 413
|
||||
case URITooLong = 414
|
||||
case UnsupportedMediaType = 415
|
||||
case RangeNotSatisfiable = 416
|
||||
case ExpectationFailed = 417
|
||||
case MisdirectedRequest = 421
|
||||
case UnprocessableEntity = 422
|
||||
case Locked = 423
|
||||
case FailedDependency = 424
|
||||
case UnorderedCollection = 425
|
||||
case UpgradeRequired = 426
|
||||
case PreconditionRequired = 428
|
||||
case TooManyRequests = 429
|
||||
case RequestHeaderFieldsTooLarge = 431
|
||||
case UnavailableForLegalReasons = 451
|
||||
case InternalServerError = 500
|
||||
case BadGateway = 502
|
||||
case ServiceUnavailable = 503
|
||||
case GatewayTimeout = 504
|
||||
case HTTPVersionNotSupported = 505
|
||||
case VariantlsoNegotiates = 506
|
||||
case InsufficientStorage = 507
|
||||
case LoopDetected = 508
|
||||
case BandwidthLimitExceeded = 509
|
||||
case NotExtended = 510
|
||||
case NetworkAuthenticationRequired = 511
|
||||
|
||||
private static let status1xx = [100: "Continue", 101: "Switching Protocols", 102: "Processing"]
|
||||
private static let status2xx = [200: "OK", 201: "Created", 202: "Accepted", 203: "Non-Authoritative Information", 204: "No Content", 205: "Reset Content", 206: "Partial Content", 207: "Multi-Status", 208: "Already Reported", 226: "IM Used"]
|
||||
private static let status3xx = [300: "Multiple Choices", 301: "Moved Permanently", 302: "Found", 303: "See Other", 304: "Not Modified", 305: "Use Proxy", 306: "Switch Proxy", 307: "Temporary Redirect", 308: "Permanent Redirect"]
|
||||
private static let status4xx = [400: "Bad Request", 401: "Unauthorized/Expired Session", 402: "Payment Required", 403: "Forbidden", 404: "Not Found", 405: "Method Not Allowed", 406: "Not Acceptable", 407: "Proxy Authentication Required", 408: "Request Timeout", 409: "Conflict", 410: "Gone", 411: "Length Required", 412: "Precondition Failed", 413: "Payload Too Large", 414: "URI Too Long", 415: "Unsupported Media Type", 416: "Range Not Satisfiable", 417: "Expectation Failed", 421: "Misdirected Request", 422: "Unprocessable Entity", 423: "Locked", 424: "Failed Dependency", 425: "Unordered Collection", 426: "Upgrade Required", 428: "Precondition Required", 429: "Too Many Requests", 431: "Request Header Fields Too Large", 451: "Unavailable For Legal Reasons"]
|
||||
private static let status5xx = [500: "Internal Server Error", 501: "Not Implemented", 502: "Bad Gateway", 503: "Service Unavailable", 504: "Gateway Timeout", 505: "HTTP Version Not Supported", 506: "Variant Also Negotiates", 507: "Insufficient Storage", 508: "Loop Detected", 509: "Bandwidth Limit Exceeded", 510: "Not Extended", 511: "Network Authentication Required"]
|
||||
|
||||
public var description: String {
|
||||
switch self.rawValue {
|
||||
case 100...102: return FileProviderHTTPErrorCode.status1xx[self.rawValue]!
|
||||
case 200...208, 226: return FileProviderHTTPErrorCode.status2xx[self.rawValue]!
|
||||
case 300...308: return FileProviderHTTPErrorCode.status3xx[self.rawValue]!
|
||||
case 400...417, 421...426: fallthrough
|
||||
case 428, 429, 431, 451: return FileProviderHTTPErrorCode.status4xx[self.rawValue]!
|
||||
case 500...511: return FileProviderHTTPErrorCode.status5xx[self.rawValue]!
|
||||
default: return typeDescription
|
||||
}
|
||||
}
|
||||
|
||||
public var typeDescription: String {
|
||||
switch self.rawValue {
|
||||
case 100...199: return "Informational"
|
||||
case 200...299: return "Success"
|
||||
case 300...399: return "Redirection"
|
||||
case 400...499: return "Client Error"
|
||||
case 500...599: return "Server Error"
|
||||
default: return "Server Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,11 +12,13 @@ public final class WebDavFileObject: FileObject {
|
||||
public let contentType: String
|
||||
public let entryTag: String?
|
||||
|
||||
public init(absoluteURL: NSURL, name: String, path: String, size: Int64, contentType: String, createdDate: NSDate?, modifiedDate: NSDate?, fileType: FileType, isHidden: Bool, isReadOnly: Bool, entryTag: String?) {
|
||||
// codebeat:disable[ARITY]
|
||||
public init(absoluteURL: NSURL, name: String, path: String, size: Int64 = -1, contentType: String = "", createdDate: NSDate? = nil, modifiedDate: NSDate? = nil, fileType: FileType = .Regular, isHidden: Bool = false, isReadOnly: Bool = false, entryTag: String? = nil) {
|
||||
self.contentType = contentType
|
||||
self.entryTag = entryTag
|
||||
super.init(absoluteURL: absoluteURL, name: name, path: path, size: size, createdDate: createdDate, modifiedDate: modifiedDate, fileType: fileType, isHidden: isHidden, isReadOnly: isReadOnly)
|
||||
}
|
||||
// codebeat:enable[ARITY]
|
||||
}
|
||||
|
||||
// Because this class uses NSURLSession, it's necessary to disable App Transport Security
|
||||
@@ -36,11 +38,13 @@ public class WebDAVFileProvider: NSObject, FileProviderBasic {
|
||||
public let credential: NSURLCredential?
|
||||
|
||||
private var _session: NSURLSession?
|
||||
private var sessionDelegate: SessionDelegate?
|
||||
private var session: NSURLSession {
|
||||
if _session == nil {
|
||||
self.sessionDelegate = SessionDelegate(fileProvider: self, credential: credential)
|
||||
let queue = NSOperationQueue()
|
||||
//queue.underlyingQueue = dispatch_queue
|
||||
_session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration(), delegate: self, delegateQueue: queue)
|
||||
_session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration(), delegate: sessionDelegate, delegateQueue: queue)
|
||||
}
|
||||
return _session!
|
||||
}
|
||||
@@ -177,7 +181,7 @@ extension WebDAVFileProvider: FileProviderOperations {
|
||||
completionHandler?(error: responseError ?? error)
|
||||
self.delegateNotify(.Create(path: (path as NSString).stringByAppendingPathComponent(fileAttribs.name)), error: responseError ?? error)
|
||||
}
|
||||
task.taskDescription = self.dictionaryToJSON(["type": "Create", "source": (path as NSString).stringByAppendingPathComponent(fileAttribs.name)])
|
||||
task.taskDescription = dictionaryToJSON(["type": "Create", "source": (path as NSString).stringByAppendingPathComponent(fileAttribs.name)])
|
||||
task.resume()
|
||||
}
|
||||
|
||||
@@ -258,7 +262,7 @@ extension WebDAVFileProvider: FileProviderOperations {
|
||||
completionHandler?(error: responseError ?? error)
|
||||
self.delegateNotify(.Move(source: localFile.uw_absoluteString, destination: toPath), error: responseError ?? error)
|
||||
}
|
||||
task.taskDescription = self.dictionaryToJSON(["type": "Copy", "source": localFile.uw_absoluteString, "dest": toPath])
|
||||
task.taskDescription = dictionaryToJSON(["type": "Copy", "source": localFile.uw_absoluteString, "dest": toPath])
|
||||
task.resume()
|
||||
}
|
||||
|
||||
@@ -280,7 +284,7 @@ extension WebDAVFileProvider: FileProviderOperations {
|
||||
}
|
||||
completionHandler?(error: responseError ?? error)
|
||||
}
|
||||
task.taskDescription = self.dictionaryToJSON(["type": "Copy", "source": path, "dest": toLocalURL.uw_absoluteString])
|
||||
task.taskDescription = dictionaryToJSON(["type": "Copy", "source": path, "dest": toLocalURL.uw_absoluteString])
|
||||
task.resume()
|
||||
}
|
||||
}
|
||||
@@ -330,7 +334,7 @@ extension WebDAVFileProvider: FileProviderReadWrite {
|
||||
self.moveItemAtPath((path as NSString).stringByAppendingPathExtension("tmp")!, toPath: path, completionHandler: completionHandler)
|
||||
}
|
||||
}
|
||||
task.taskDescription = self.dictionaryToJSON(["type": "Modify", "source": path])
|
||||
task.taskDescription = dictionaryToJSON(["type": "Modify", "source": path])
|
||||
task.resume()
|
||||
}
|
||||
|
||||
@@ -407,49 +411,8 @@ internal extension WebDAVFileProvider {
|
||||
break
|
||||
}
|
||||
for responseNode in rootnode[responsetag].all ?? [] {
|
||||
var hreftag = "href"
|
||||
var statustag = "status"
|
||||
var propstattag = "propstat"
|
||||
for node in responseNode.children ?? [] {
|
||||
if node.name.lowercaseString.hasSuffix("href") {
|
||||
hreftag = node.name
|
||||
}
|
||||
if node.name.lowercaseString.hasSuffix("status") {
|
||||
statustag = node.name
|
||||
}
|
||||
if node.name.lowercaseString.hasSuffix("propstat") {
|
||||
propstattag = node.name
|
||||
}
|
||||
}
|
||||
let href = responseNode[hreftag].value
|
||||
if let href = href, hrefURL = NSURL(string: href) {
|
||||
var status: Int?
|
||||
let statusDesc = (responseNode[statustag].stringValue).componentsSeparatedByString(" ")
|
||||
if statusDesc.count > 2 {
|
||||
status = Int(statusDesc[1])
|
||||
}
|
||||
var propDic = [String: String]()
|
||||
let propStatNode = responseNode[propstattag]
|
||||
for node in propStatNode.children ?? [] where node.name.lowercaseString.hasSuffix("status"){
|
||||
statustag = node.name
|
||||
break
|
||||
}
|
||||
let statusDesc2 = (propStatNode[statustag].stringValue).componentsSeparatedByString(" ")
|
||||
if statusDesc2.count > 2 {
|
||||
status = Int(statusDesc2[1])
|
||||
}
|
||||
var proptag = "prop"
|
||||
for tnode in propStatNode.children ?? [] where tnode.name.lowercaseString.hasSuffix("prop") {
|
||||
proptag = tnode.name
|
||||
break
|
||||
}
|
||||
for propItemNode in propStatNode[proptag].children ?? [] {
|
||||
propDic[propItemNode.name.componentsSeparatedByString(":").last!.lowercaseString] = propItemNode.value
|
||||
if propItemNode.name.hasSuffix("resourcetype") && propItemNode.xmlString.containsString("collection") {
|
||||
propDic["getcontenttype"] = "httpd/unix-directory"
|
||||
}
|
||||
}
|
||||
result.append(DavResponse(href: hrefURL, hrefString: href, status: status, prop: propDic))
|
||||
if let davResponse = mapNodeToDavResponse(responseNode) {
|
||||
result.append(davResponse)
|
||||
}
|
||||
}
|
||||
} catch _ {
|
||||
@@ -457,6 +420,54 @@ internal extension WebDAVFileProvider {
|
||||
return result
|
||||
}
|
||||
|
||||
private func mapNodeToDavResponse(node: AEXMLElement) -> DavResponse? {
|
||||
var hreftag = "href"
|
||||
var statustag = "status"
|
||||
var propstattag = "propstat"
|
||||
for node in node.children ?? [] {
|
||||
if node.name.lowercaseString.hasSuffix("href") {
|
||||
hreftag = node.name
|
||||
}
|
||||
if node.name.lowercaseString.hasSuffix("status") {
|
||||
statustag = node.name
|
||||
}
|
||||
if node.name.lowercaseString.hasSuffix("propstat") {
|
||||
propstattag = node.name
|
||||
}
|
||||
}
|
||||
let href = node[hreftag].value
|
||||
if let href = href, hrefURL = NSURL(string: href) {
|
||||
var status: Int?
|
||||
let statusDesc = (node[statustag].stringValue).componentsSeparatedByString(" ")
|
||||
if statusDesc.count > 2 {
|
||||
status = Int(statusDesc[1])
|
||||
}
|
||||
var propDic = [String: String]()
|
||||
let propStatNode = node[propstattag]
|
||||
for node in propStatNode.children ?? [] where node.name.lowercaseString.hasSuffix("status"){
|
||||
statustag = node.name
|
||||
break
|
||||
}
|
||||
let statusDesc2 = (propStatNode[statustag].stringValue).componentsSeparatedByString(" ")
|
||||
if statusDesc2.count > 2 {
|
||||
status = Int(statusDesc2[1])
|
||||
}
|
||||
var proptag = "prop"
|
||||
for tnode in propStatNode.children ?? [] where tnode.name.lowercaseString.hasSuffix("prop") {
|
||||
proptag = tnode.name
|
||||
break
|
||||
}
|
||||
for propItemNode in propStatNode[proptag].children ?? [] {
|
||||
propDic[propItemNode.name.componentsSeparatedByString(":").last!.lowercaseString] = propItemNode.value
|
||||
if propItemNode.name.hasSuffix("resourcetype") && propItemNode.xmlString.containsString("collection") {
|
||||
propDic["getcontenttype"] = "httpd/unix-directory"
|
||||
}
|
||||
}
|
||||
return DavResponse(href: hrefURL, hrefString: href, status: status, prop: propDic)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
private func mapToFileObject(davResponse: DavResponse) -> WebDavFileObject {
|
||||
var href = davResponse.href
|
||||
if href.baseURL == nil {
|
||||
@@ -483,65 +494,6 @@ internal extension WebDAVFileProvider {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: URLSession delegate
|
||||
extension WebDAVFileProvider: NSURLSessionDataDelegate, NSURLSessionDownloadDelegate {
|
||||
public func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) {
|
||||
return
|
||||
}
|
||||
|
||||
public func URLSession(session: NSURLSession, task: NSURLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
|
||||
guard let desc = task.taskDescription, let json = jsonToDictionary(desc) else {
|
||||
return
|
||||
}
|
||||
guard let type = json["type"] as? String, let source = json["source"] as? String else {
|
||||
return
|
||||
}
|
||||
let dest = json["dest"] as? String
|
||||
let op : FileOperation
|
||||
switch type {
|
||||
case "Create":
|
||||
op = .Create(path: source)
|
||||
case "Copy":
|
||||
guard let dest = dest else { return }
|
||||
op = .Copy(source: source, destination: dest)
|
||||
case "Move":
|
||||
guard let dest = dest else { return }
|
||||
op = .Move(source: source, destination: dest)
|
||||
case "Modify":
|
||||
op = .Modify(path: source)
|
||||
case "Remove":
|
||||
op = .Remove(path: source)
|
||||
case "Link":
|
||||
guard let dest = dest else { return }
|
||||
op = .Link(link: source, target: dest)
|
||||
default:
|
||||
return
|
||||
}
|
||||
|
||||
let progress = Float(totalBytesSent) / Float(totalBytesExpectedToSend)
|
||||
|
||||
self.delegate?.fileproviderProgress(self, operation: op, progress: progress)
|
||||
}
|
||||
|
||||
public func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
|
||||
guard let desc = downloadTask.taskDescription, let json = jsonToDictionary(desc), let source = json["source"] as? String, dest = json["dest"] as? String else {
|
||||
return
|
||||
}
|
||||
|
||||
self.delegate?.fileproviderProgress(self, operation: .Copy(source: source, destination: dest), progress: Float(totalBytesWritten) / Float(totalBytesExpectedToWrite))
|
||||
}
|
||||
|
||||
public func URLSession(session: NSURLSession, task: NSURLSessionTask, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
|
||||
let deposition: NSURLSessionAuthChallengeDisposition = credential != nil ? .UseCredential : .PerformDefaultHandling
|
||||
completionHandler(deposition, credential)
|
||||
}
|
||||
|
||||
public func URLSession(session: NSURLSession, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
|
||||
let deposition: NSURLSessionAuthChallengeDisposition = credential != nil ? .UseCredential : .PerformDefaultHandling
|
||||
completionHandler(deposition, credential)
|
||||
}
|
||||
}
|
||||
|
||||
public struct FileProviderWebDavError: ErrorType, CustomStringConvertible {
|
||||
public let code: FileProviderHTTPErrorCode
|
||||
public let url: NSURL
|
||||
@@ -549,97 +501,4 @@ public struct FileProviderWebDavError: ErrorType, CustomStringConvertible {
|
||||
public var description: String {
|
||||
return code.description
|
||||
}
|
||||
}
|
||||
|
||||
public enum FileProviderHTTPErrorCode: Int {
|
||||
case Continue = 100
|
||||
case SwitchingProtocols = 101
|
||||
case Processing = 102
|
||||
case OK = 200
|
||||
case Created = 201
|
||||
case Accepted = 202
|
||||
case NonAuthoritativeInformation = 203
|
||||
case NoContent = 204
|
||||
case ResetContent = 205
|
||||
case PartialContent = 206
|
||||
case MultiStatus = 207
|
||||
case AlreadyReported = 208
|
||||
case IMUsed = 226
|
||||
case MultipleChoices = 300
|
||||
case MovedPermanently = 301
|
||||
case Found = 302
|
||||
case SeeOther = 303
|
||||
case NotModified = 304
|
||||
case UseProxy = 305
|
||||
case SwitchProxy = 306
|
||||
case TemporaryRedirect = 307
|
||||
case PermanentRedirect = 308
|
||||
case BadRequest = 400
|
||||
case Unauthorized = 401
|
||||
case PaymentRequired = 402
|
||||
case Forbidden = 403
|
||||
case NotFound = 404
|
||||
case MethodNotAllowed = 405
|
||||
case NotAcceptable = 406
|
||||
case ProxyAuthenticationRequired = 407
|
||||
case RequestTimeout = 408
|
||||
case Conflict = 409
|
||||
case Gone = 410
|
||||
case LengthRequired = 411
|
||||
case PreconditionFailed = 412
|
||||
case PayloadTooLarge = 413
|
||||
case URITooLong = 414
|
||||
case UnsupportedMediaType = 415
|
||||
case RangeNotSatisfiable = 416
|
||||
case ExpectationFailed = 417
|
||||
case MisdirectedRequest = 421
|
||||
case UnprocessableEntity = 422
|
||||
case Locked = 423
|
||||
case FailedDependency = 424
|
||||
case UnorderedCollection = 425
|
||||
case UpgradeRequired = 426
|
||||
case PreconditionRequired = 428
|
||||
case TooManyRequests = 429
|
||||
case RequestHeaderFieldsTooLarge = 431
|
||||
case UnavailableForLegalReasons = 451
|
||||
case InternalServerError = 500
|
||||
case BadGateway = 502
|
||||
case ServiceUnavailable = 503
|
||||
case GatewayTimeout = 504
|
||||
case HTTPVersionNotSupported = 505
|
||||
case VariantlsoNegotiates = 506
|
||||
case InsufficientStorage = 507
|
||||
case LoopDetected = 508
|
||||
case BandwidthLimitExceeded = 509
|
||||
case NotExtended = 510
|
||||
case NetworkAuthenticationRequired = 511
|
||||
|
||||
private static let status1xx = [100: "Continue", 101: "Switching Protocols", 102: "Processing"]
|
||||
private static let status2xx = [200: "OK", 201: "Created", 202: "Accepted", 203: "Non-Authoritative Information", 204: "No Content", 205: "Reset Content", 206: "Partial Content", 207: "Multi-Status", 208: "Already Reported", 226: "IM Used"]
|
||||
private static let status3xx = [300: "Multiple Choices", 301: "Moved Permanently", 302: "Found", 303: "See Other", 304: "Not Modified", 305: "Use Proxy", 306: "Switch Proxy", 307: "Temporary Redirect", 308: "Permanent Redirect"]
|
||||
private static let status4xx = [400: "Bad Request", 401: "Unauthorized/Expired Session", 402: "Payment Required", 403: "Forbidden", 404: "Not Found", 405: "Method Not Allowed", 406: "Not Acceptable", 407: "Proxy Authentication Required", 408: "Request Timeout", 409: "Conflict", 410: "Gone", 411: "Length Required", 412: "Precondition Failed", 413: "Payload Too Large", 414: "URI Too Long", 415: "Unsupported Media Type", 416: "Range Not Satisfiable", 417: "Expectation Failed", 421: "Misdirected Request", 422: "Unprocessable Entity", 423: "Locked", 424: "Failed Dependency", 425: "Unordered Collection", 426: "Upgrade Required", 428: "Precondition Required", 429: "Too Many Requests", 431: "Request Header Fields Too Large", 451: "Unavailable For Legal Reasons"]
|
||||
private static let status5xx = [500: "Internal Server Error", 501: "Not Implemented", 502: "Bad Gateway", 503: "Service Unavailable", 504: "Gateway Timeout", 505: "HTTP Version Not Supported", 506: "Variant Also Negotiates", 507: "Insufficient Storage", 508: "Loop Detected", 509: "Bandwidth Limit Exceeded", 510: "Not Extended", 511: "Network Authentication Required"]
|
||||
|
||||
public var description: String {
|
||||
switch self.rawValue {
|
||||
case 100...102: return FileProviderHTTPErrorCode.status1xx[self.rawValue]!
|
||||
case 200...208, 226: return FileProviderHTTPErrorCode.status2xx[self.rawValue]!
|
||||
case 300...308: return FileProviderHTTPErrorCode.status3xx[self.rawValue]!
|
||||
case 400...417, 421...426: fallthrough
|
||||
case 428, 429, 431, 451: return FileProviderHTTPErrorCode.status4xx[self.rawValue]!
|
||||
case 500...511: return FileProviderHTTPErrorCode.status5xx[self.rawValue]!
|
||||
default: return typeDescription
|
||||
}
|
||||
}
|
||||
|
||||
public var typeDescription: String {
|
||||
switch self.rawValue {
|
||||
case 100...199: return "Informational"
|
||||
case 200...299: return "Success"
|
||||
case 300...399: return "Redirection"
|
||||
case 400...499: return "Client Error"
|
||||
case 500...599: return "Server Error"
|
||||
default: return "Server Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user