Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 940c7c1028 | |||
| b4ace7e680 |
@@ -16,7 +16,7 @@ Pod::Spec.new do |s|
|
||||
#
|
||||
|
||||
s.name = "FileProvider"
|
||||
s.version = "0.3.3"
|
||||
s.version = "0.4.0"
|
||||
s.summary = "NSFileManager replacement for Local and Remote (WebDAV/Dropbox/SMB2) files on iOS and MacOS."
|
||||
|
||||
# This description is used to generate tags and improve search results.
|
||||
|
||||
@@ -23,8 +23,8 @@ Local and WebDAV providers are fully tested and can be used in production enviro
|
||||
|
||||
- [x] **LocalFileProvider** a wrapper around `NSFileManager` with some additions like searching and reading a portion of file.
|
||||
- [x] **WebDAVFileProvider** WebDAV protocol is usual file transmission system on Macs.
|
||||
- [x] **DropboxFileProvider** *implemented but not tested*
|
||||
- [ ] **SMBFileProvider** SMB/CIFS and SMB2/3 are file and printer sharing protocol which is originated from IBM & Microsoft and SMB2/3 is now replacing AFP protocol on MacOS. I implemented data types and some basic functions but *main interface is not implemented yet!*
|
||||
- [ ] **DropboxFileProvider** *partially implemented*
|
||||
- [ ] **FTPFileProvider**
|
||||
- [ ] **AmazonS3FileProvider**
|
||||
|
||||
@@ -155,26 +155,36 @@ There is a `FileObject` class which holds file attributes like size and creation
|
||||
For a single file:
|
||||
|
||||
documentsProvider.attributesOfItemAtPath(path: "/file.txt", completionHandler: {
|
||||
(attributes: LocalFileObject?, error: ErrorType?) -> Void} in
|
||||
(attributes: LocalFileObject?, error: ErrorType?) -> Void in
|
||||
if let attributes = attributes {
|
||||
print("File Size: \(attributes.size)")
|
||||
print("Creation Date: \(attributes.createdDate)")
|
||||
print("Modification Date: \(modifiedDate)")
|
||||
print("Is Read Only: \(isReadOnly)")
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
To get list of files in a directory:
|
||||
|
||||
documentsProvider.contentsOfDirectoryAtPath(path: "/", completionHandler: {
|
||||
(contents: [LocalFileObject], error: ErrorType?) -> Void} in
|
||||
(contents: [LocalFileObject], error: ErrorType?) -> Void in
|
||||
for file in contents {
|
||||
print("Name: \(attributes.name)")
|
||||
print("Size: \(attributes.size)")
|
||||
print("Creation Date: \(attributes.createdDate)")
|
||||
print("Modification Date: \(modifiedDate)")
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
To get size of strage and used/free space:
|
||||
|
||||
func storageProperties(completionHandler: {(total: Int64, used: Int64) -> Void in
|
||||
print("Total Storage Space: \(total)")
|
||||
print("Used Space: \(used)")
|
||||
print("Free Space: \(total - frees)")
|
||||
})
|
||||
|
||||
* if this function is unavailable on provider or an error has been occurred, total space will be reported "-1" and used space "0"
|
||||
|
||||
### Change current directory
|
||||
|
||||
|
||||
@@ -8,30 +8,12 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
public enum FileProviderDropboxErrorCode: Int {
|
||||
case BadInputParameter = 400
|
||||
case ExpiredToken = 401
|
||||
case Forbidden = 403
|
||||
case Endpoint = 409
|
||||
case TooManyRequests = 429
|
||||
case InternalServer = 500
|
||||
case BadGateway = 502
|
||||
}
|
||||
|
||||
public struct FileProviderDropboxError: ErrorType, CustomStringConvertible {
|
||||
public let code: FileProviderDropboxErrorCode
|
||||
public let code: FileProviderHTTPErrorCode
|
||||
public let path: String
|
||||
|
||||
public var description: String {
|
||||
switch code {
|
||||
case .BadInputParameter: return "Bad input parameter."
|
||||
case .ExpiredToken: return "Bad or expired token. To fix this, you should re-authenticate the user."
|
||||
case .Forbidden: return "Forbidden."
|
||||
case .Endpoint: return "Endpoint-specific error."
|
||||
case .TooManyRequests: return "Your app is making too many requests"
|
||||
case .InternalServer: return "An error occurred on the Dropbox servers."
|
||||
case .BadGateway: return "An error occurred on the Dropbox servers."
|
||||
}
|
||||
return code.description
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,11 +71,13 @@ public class DropboxFileProvider: NSObject, FileProviderBasic {
|
||||
}
|
||||
|
||||
public func contentsOfDirectoryAtPath(path: String, completionHandler: ((contents: [FileObject], error: ErrorType?) -> Void)) {
|
||||
NotImplemented()
|
||||
list(path) { (contents, cursor, error) in
|
||||
completionHandler(contents: contents, error: error)
|
||||
}
|
||||
}
|
||||
|
||||
public func attributesOfItemAtPath(path: String, completionHandler: ((attributes: FileObject?, error: ErrorType?) -> Void)) {
|
||||
let url = NSURL(string: "https://api.dropboxapi.com/2/files/list_revisions")!
|
||||
let url = NSURL(string: "https://api.dropboxapi.com/2/files/get_metadata")!
|
||||
let request = NSMutableURLRequest(URL: url)
|
||||
request.HTTPMethod = "POST"
|
||||
request.setValue("Bearer \(credential?.password ?? "")", forHTTPHeaderField: "Authorization")
|
||||
@@ -105,14 +89,11 @@ public class DropboxFileProvider: NSObject, FileProviderBasic {
|
||||
defer {
|
||||
self.delegateNotify(FileOperation.Create(path: path), error: error)
|
||||
}
|
||||
let code = FileProviderDropboxErrorCode(rawValue: response.statusCode)
|
||||
let code = FileProviderHTTPErrorCode(rawValue: response.statusCode)
|
||||
let dbError: FileProviderDropboxError? = code != nil ? FileProviderDropboxError(code: code!, path: path) : nil
|
||||
if let data = data, let jsonStr = String(data: data, encoding: NSUTF8StringEncoding) {
|
||||
let json = self.jsonToDictionary(jsonStr)
|
||||
if (json?["is_deleted"] as? NSNumber)?.boolValue ?? false, let entries = json?["entries"] as? [AnyObject] where entries.count > 0 , let entry = entries[0] as? [String: AnyObject], let file = self.mapToFileObject(entry) {
|
||||
completionHandler(attributes: file, error: dbError)
|
||||
return
|
||||
}
|
||||
if let data = data, let jsonStr = String(data: data, encoding: NSUTF8StringEncoding), let json = self.jsonToDictionary(jsonStr), let file = self.mapToFileObject(json) {
|
||||
completionHandler(attributes: file, error: dbError)
|
||||
return
|
||||
}
|
||||
completionHandler(attributes: nil, error: dbError)
|
||||
return
|
||||
@@ -122,6 +103,23 @@ public class DropboxFileProvider: NSObject, FileProviderBasic {
|
||||
task.resume()
|
||||
}
|
||||
|
||||
public func storageProperties(completionHandler: ((total: Int64, used: Int64) -> Void)) {
|
||||
let url = NSURL(string: "https://api.dropboxapi.com/2/users/get_space_usage")!
|
||||
let request = NSMutableURLRequest(URL: url)
|
||||
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) {
|
||||
let totalSize = ((json["allocation"] as? NSDictionary)?["allocated"] as? NSNumber)?.longLongValue ?? -1
|
||||
let usedSize = (json["used"] as? NSNumber)?.longLongValue ?? 0
|
||||
completionHandler(total: totalSize, used: usedSize)
|
||||
return
|
||||
}
|
||||
completionHandler(total: -1, used: 0)
|
||||
}
|
||||
task.resume()
|
||||
}
|
||||
|
||||
public weak var fileOperationDelegate: FileOperationDelegate?
|
||||
}
|
||||
|
||||
@@ -181,7 +179,7 @@ extension DropboxFileProvider: FileProviderOperations {
|
||||
request.HTTPBody = dictionaryToJSON(requestDictionary)?.dataUsingEncoding(NSUTF8StringEncoding)
|
||||
let task = session.dataTaskWithRequest(request) { (data, response, error) in
|
||||
if let response = response as? NSHTTPURLResponse {
|
||||
let code = FileProviderDropboxErrorCode(rawValue: response.statusCode)
|
||||
let code = FileProviderHTTPErrorCode(rawValue: response.statusCode)
|
||||
let dbError: FileProviderDropboxError? = code != nil ? FileProviderDropboxError(code: code!, path: path ?? fromPath ?? "") : nil
|
||||
defer {
|
||||
self.delegateNotify(operation, error: error ?? dbError)
|
||||
@@ -198,15 +196,12 @@ extension DropboxFileProvider: FileProviderOperations {
|
||||
}
|
||||
|
||||
public func copyLocalFileToPath(localFile: NSURL, toPath: String, completionHandler: SimpleCompletionHandler) {
|
||||
NotImplemented()
|
||||
let request = NSMutableURLRequest(URL: absoluteURL(toPath))
|
||||
request.HTTPMethod = "PUT"
|
||||
let task = session.uploadTaskWithRequest(request, fromFile: localFile) { (data, response, error) in
|
||||
guard let data = NSData(contentsOfURL: localFile) else {
|
||||
let error = throwError(localFile.uw_absoluteString, code: NSURLError.FileDoesNotExist)
|
||||
completionHandler?(error: error)
|
||||
self.delegateNotify(.Move(source: localFile.uw_absoluteString, destination: toPath), error: error)
|
||||
return
|
||||
}
|
||||
task.taskDescription = self.dictionaryToJSON(["type": "Copy", "source": localFile.uw_absoluteString, "dest": toPath])
|
||||
task.resume()
|
||||
upload_simple(toPath, data: data, overwrite: true, operation: .Copy(source: localFile.absoluteString, destination: toPath), completionHandler: completionHandler)
|
||||
}
|
||||
|
||||
public func copyPathToLocalFile(path: String, toLocalURL destURL: NSURL, completionHandler: SimpleCompletionHandler) {
|
||||
@@ -219,7 +214,7 @@ extension DropboxFileProvider: FileProviderOperations {
|
||||
request.setValue(dictionaryToJSON(requestDictionary), forHTTPHeaderField: "Dropbox-API-Arg")
|
||||
let task = session.downloadTaskWithRequest(request, completionHandler: { (cacheURL, response, error) in
|
||||
guard let cacheURL = cacheURL, let httpResponse = response as? NSHTTPURLResponse where httpResponse.statusCode < 300 else {
|
||||
let code = FileProviderDropboxErrorCode(rawValue: (response as? NSHTTPURLResponse)?.statusCode ?? -1)
|
||||
let code = FileProviderHTTPErrorCode(rawValue: (response as? NSHTTPURLResponse)?.statusCode ?? -1)
|
||||
let dbError: FileProviderDropboxError? = code != nil ? FileProviderDropboxError(code: code!, path: path) : nil
|
||||
completionHandler?(error: dbError ?? error)
|
||||
return
|
||||
@@ -231,6 +226,7 @@ extension DropboxFileProvider: FileProviderOperations {
|
||||
completionHandler?(error: e)
|
||||
}
|
||||
})
|
||||
task.taskDescription = self.dictionaryToJSON(["type": "Copy", "source": path, "dest": destURL.uw_absoluteString])
|
||||
task.resume()
|
||||
}
|
||||
}
|
||||
@@ -255,7 +251,7 @@ extension DropboxFileProvider: FileProviderReadWrite {
|
||||
request.setValue(dictionaryToJSON(requestDictionary), forHTTPHeaderField: "Dropbox-API-Arg")
|
||||
let task = session.downloadTaskWithRequest(request, completionHandler: { (cacheURL, response, error) in
|
||||
guard let cacheURL = cacheURL, let httpResponse = response as? NSHTTPURLResponse where httpResponse.statusCode < 300 else {
|
||||
let code = FileProviderDropboxErrorCode(rawValue: (response as? NSHTTPURLResponse)?.statusCode ?? -1)
|
||||
let code = FileProviderHTTPErrorCode(rawValue: (response as? NSHTTPURLResponse)?.statusCode ?? -1)
|
||||
let dbError: FileProviderDropboxError? = code != nil ? FileProviderDropboxError(code: code!, path: path) : nil
|
||||
completionHandler(contents: nil, error: dbError ?? error)
|
||||
return
|
||||
@@ -272,32 +268,22 @@ extension DropboxFileProvider: FileProviderReadWrite {
|
||||
}
|
||||
|
||||
public func writeContentsAtPath(path: String, contents data: NSData, atomically: Bool = false, completionHandler: SimpleCompletionHandler) {
|
||||
NotImplemented()
|
||||
let url = atomically ? absoluteURL(path).uw_URLByAppendingPathExtension("tmp") : absoluteURL(path)
|
||||
let request = NSMutableURLRequest(URL: url)
|
||||
request.HTTPMethod = "PUT"
|
||||
let task = session.uploadTaskWithRequest(request, fromData: data) { (data, response, error) in
|
||||
defer {
|
||||
self.delegateNotify(.Modify(path: path), error: error)
|
||||
}
|
||||
if atomically {
|
||||
self.moveItemAtPath((path as NSString).stringByAppendingPathExtension("tmp")!, toPath: path, completionHandler: completionHandler)
|
||||
}
|
||||
if let error = error {
|
||||
// If there is no error, completionHandler has been executed by move command
|
||||
completionHandler?(error: error)
|
||||
}
|
||||
}
|
||||
task.taskDescription = self.dictionaryToJSON(["type": "Modify", "source": path])
|
||||
task.resume()
|
||||
// FIXME: remove 150MB restriction
|
||||
upload_simple(path, data: data, overwrite: true, operation: .Modify(path: path), completionHandler: completionHandler)
|
||||
}
|
||||
|
||||
public func searchFilesAtPath(path: String, recursive: Bool, query: String, foundItemHandler: ((FileObject) -> Void)?, completionHandler: ((files: [FileObject], error: ErrorType?) -> Void)) {
|
||||
NotImplemented()
|
||||
var foundFiles = [DropboxFileObject]()
|
||||
search(path, query: query, foundItem: { (file) in
|
||||
foundFiles.append(file)
|
||||
foundItemHandler?(file)
|
||||
}, completionHandler: { (error) in
|
||||
completionHandler(files: foundFiles, error: error)
|
||||
})
|
||||
}
|
||||
|
||||
private func registerNotifcation(path: String, eventHandler: (() -> Void)) {
|
||||
/* There is two ways to monitor folders chaging in Dropbox. Either using webooks
|
||||
/* There is two ways to monitor folders changing in Dropbox. Either using webooks
|
||||
* which means you have to implement a server to translate it to push notifications
|
||||
* or using apiv2 list_folder/longpoll method. The second one is implemeted here.
|
||||
* Tough webhooks are much more efficient, longpoll is much simpler to implement!
|
||||
@@ -308,6 +294,139 @@ extension DropboxFileProvider: FileProviderReadWrite {
|
||||
private func unregisterNotifcation(path: String) {
|
||||
NotImplemented()
|
||||
}
|
||||
|
||||
// TODO: Implement /copy_reference, /get_preview & /get_thumbnail, /get_temporary_link, /save_url, /get_account & /get_current_account
|
||||
}
|
||||
|
||||
private extension DropboxFileProvider {
|
||||
private func list(path: String, cursor: String? = nil, prevContents: [DropboxFileObject] = [], recursive: Bool = false, completionHandler: ((contents: [FileObject], cursor: String?, error: ErrorType?) -> Void)) {
|
||||
var requestDictionary = [String: AnyObject]()
|
||||
let url: NSURL
|
||||
if let cursor = cursor {
|
||||
url = NSURL(string: "https://api.dropboxapi.com/2/files/list_folder/continue")!
|
||||
requestDictionary["cursor"] = cursor
|
||||
} else {
|
||||
url = NSURL(string: "https://api.dropboxapi.com/2/files/list_folder")!
|
||||
requestDictionary["path"] = correctPath(path)
|
||||
requestDictionary["recursive"] = NSNumber(bool: recursive)
|
||||
}
|
||||
let request = NSMutableURLRequest(URL: url)
|
||||
request.HTTPMethod = "POST"
|
||||
request.setValue("Bearer \(credential?.password ?? "")", forHTTPHeaderField: "Authorization")
|
||||
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
|
||||
request.HTTPBody = dictionaryToJSON(requestDictionary)?.dataUsingEncoding(NSUTF8StringEncoding)
|
||||
let task = session.dataTaskWithRequest(request) { (data, response, error) in
|
||||
var responseError: FileProviderDropboxError?
|
||||
if let code = (response as? NSHTTPURLResponse)?.statusCode where code >= 300, let rCode = FileProviderHTTPErrorCode(rawValue: code) {
|
||||
responseError = FileProviderDropboxError(code: rCode, path: path)
|
||||
}
|
||||
if let data = data, let jsonStr = String(data: data, encoding: NSUTF8StringEncoding) {
|
||||
let json = self.jsonToDictionary(jsonStr)
|
||||
if let entries = json?["entries"] as? [AnyObject] where entries.count > 0 {
|
||||
var files = prevContents
|
||||
for entry in entries {
|
||||
if let entry = entry as? [String: AnyObject], let file = self.mapToFileObject(entry) {
|
||||
files.append(file)
|
||||
}
|
||||
}
|
||||
let ncursor = json?["cursor"] as? String
|
||||
let hasmore = (json?["has_more"] as? NSNumber)?.boolValue ?? false
|
||||
if hasmore {
|
||||
self.list(path, cursor: ncursor, prevContents: files, completionHandler: completionHandler)
|
||||
} else {
|
||||
completionHandler(contents: files, cursor: ncursor, error: responseError ?? error)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
completionHandler(contents: [], cursor: nil, error: responseError ?? error)
|
||||
}
|
||||
task.resume()
|
||||
}
|
||||
|
||||
private func upload_simple(targetPath: String, data: NSData, modifiedDate: NSDate = NSDate(), overwrite: Bool, operation: FileOperation, completionHandler: SimpleCompletionHandler) {
|
||||
assert(data.length < 150*1024*1024, "Maximum size of allowed size to upload is 150MB")
|
||||
var requestDictionary = [String: AnyObject]()
|
||||
let url: NSURL
|
||||
url = NSURL(string: "https://content.dropboxapi.com/2/files/upload")!
|
||||
requestDictionary["path"] = correctPath(targetPath)
|
||||
requestDictionary["mode"] = overwrite ? "overwrite" : "add"
|
||||
let dateFormatter = NSDateFormatter()
|
||||
dateFormatter.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ssz"
|
||||
requestDictionary["client_modified"] = dateFormatter.stringFromDate(modifiedDate)
|
||||
let request = NSMutableURLRequest(URL: url)
|
||||
request.HTTPMethod = "POST"
|
||||
request.setValue("Bearer \(credential?.password ?? "")", forHTTPHeaderField: "Authorization")
|
||||
request.setValue("application/octet-stream", forHTTPHeaderField: "Content-Type")
|
||||
request.setValue(dictionaryToJSON(requestDictionary), forHTTPHeaderField: "Dropbox-API-Arg")
|
||||
request.HTTPBody = data
|
||||
let task = session.uploadTaskWithRequest(request, fromData: data) { (data, response, error) in
|
||||
var responseError: FileProviderDropboxError?
|
||||
if let code = (response as? NSHTTPURLResponse)?.statusCode where code >= 300, let rCode = FileProviderHTTPErrorCode(rawValue: code) {
|
||||
responseError = FileProviderDropboxError(code: rCode, path: targetPath)
|
||||
}
|
||||
defer {
|
||||
self.delegateNotify(.Create(path: targetPath), error: responseError ?? error)
|
||||
}
|
||||
completionHandler?(error: responseError ?? error)
|
||||
}
|
||||
var dic: [String: AnyObject] = ["type": operation.description]
|
||||
switch operation {
|
||||
case .Create(path: let s):
|
||||
dic["source"] = s
|
||||
case .Copy(source: let s, destination: let d):
|
||||
dic["source"] = s
|
||||
dic["dest"] = d
|
||||
case .Modify(path: let s):
|
||||
dic["source"] = s
|
||||
case .Move(source: let s, destination: let d):
|
||||
dic["source"] = s
|
||||
dic["dest"] = d
|
||||
default:
|
||||
break
|
||||
}
|
||||
task.taskDescription = self.dictionaryToJSON(dic)
|
||||
task.resume()
|
||||
}
|
||||
|
||||
func search(startPath: String = "", query: String, start: Int = 0, maxResultPerPage: Int = 25, foundItem:((file: DropboxFileObject) -> Void), completionHandler: ((error: ErrorType?) -> Void)) {
|
||||
let url = NSURL(string: "https://api.dropboxapi.com/2/files/search")!
|
||||
let request = NSMutableURLRequest(URL: url)
|
||||
request.HTTPMethod = "POST"
|
||||
request.setValue("Bearer \(credential?.password ?? "")", forHTTPHeaderField: "Authorization")
|
||||
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
|
||||
var requestDictionary: [String: AnyObject] = ["path": startPath]
|
||||
requestDictionary["query"] = query
|
||||
requestDictionary["start"] = start
|
||||
requestDictionary["max_results"] = maxResultPerPage
|
||||
request.HTTPBody = dictionaryToJSON(requestDictionary)?.dataUsingEncoding(NSUTF8StringEncoding)
|
||||
let task = session.dataTaskWithRequest(request) { (data, response, error) in
|
||||
var responseError: FileProviderDropboxError?
|
||||
if let code = (response as? NSHTTPURLResponse)?.statusCode where code >= 300, let rCode = FileProviderHTTPErrorCode(rawValue: code) {
|
||||
responseError = FileProviderDropboxError(code: rCode, path: startPath)
|
||||
}
|
||||
if let data = data, let jsonStr = String(data: data, encoding: NSUTF8StringEncoding) {
|
||||
let json = self.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) {
|
||||
foundItem(file: file)
|
||||
}
|
||||
}
|
||||
let rstart = json?["start"] as? Int
|
||||
let hasmore = (json?["more"] as? NSNumber)?.boolValue ?? false
|
||||
if hasmore, let rstart = rstart {
|
||||
self.search(startPath, query: query, start: rstart + entries.count, maxResultPerPage: maxResultPerPage, foundItem: foundItem, completionHandler: completionHandler)
|
||||
} else {
|
||||
completionHandler(error: responseError ?? error)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
completionHandler(error: responseError ?? error)
|
||||
}
|
||||
task.resume()
|
||||
}
|
||||
}
|
||||
|
||||
internal extension DropboxFileProvider {
|
||||
|
||||
@@ -122,6 +122,8 @@ public protocol FileProviderBasic: class {
|
||||
*/
|
||||
func contentsOfDirectoryAtPath(path: String, completionHandler: ((contents: [FileObject], error: ErrorType?) -> Void))
|
||||
func attributesOfItemAtPath(path: String, completionHandler: ((attributes: FileObject?, error: ErrorType?) -> Void))
|
||||
|
||||
func storageProperties(completionHandler: ((total: Int64, used: Int64) -> Void))
|
||||
}
|
||||
|
||||
public protocol FileProviderOperations: FileProviderBasic {
|
||||
|
||||
@@ -85,6 +85,13 @@ public class LocalFileProvider: FileProvider, FileProviderMonitor {
|
||||
return fileAttr
|
||||
}
|
||||
|
||||
public func storageProperties(completionHandler: ((total: Int64, used: Int64) -> Void)) {
|
||||
let dict = (try? NSFileManager.defaultManager().attributesOfFileSystemForPath(baseURL?.path ?? "/")) as NSDictionary?;
|
||||
let totalSize = dict?.objectForKey(NSFileSystemSize)?.longLongValue ?? -1;
|
||||
let freeSize = dict?.objectForKey(NSFileSystemFreeSize)?.longLongValue ?? 0;
|
||||
completionHandler(total: totalSize, used: totalSize - freeSize)
|
||||
}
|
||||
|
||||
public func attributesOfItemAtPath(path: String, completionHandler: ((attributes: FileObject?, error: ErrorType?) -> Void)) {
|
||||
dispatch_async(dispatch_queue) {
|
||||
completionHandler(attributes: self.attributesOfItemAtURL(self.absoluteURL(path)), error: nil)
|
||||
|
||||
@@ -40,6 +40,10 @@ public class SMBFileProvider: FileProvider, FileProviderMonitor {
|
||||
NotImplemented()
|
||||
}
|
||||
|
||||
public func storageProperties(completionHandler: ((total: Int64, used: Int64) -> Void)) {
|
||||
NotImplemented()
|
||||
}
|
||||
|
||||
public weak var fileOperationDelegate: FileOperationDelegate?
|
||||
|
||||
public func createFolder(folderName: String, atPath: String, completionHandler: SimpleCompletionHandler) {
|
||||
|
||||
@@ -8,45 +8,6 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
public enum FileProviderWebDavErrorCode: Int {
|
||||
case OK = 200
|
||||
case Created = 201
|
||||
case NoContent = 204
|
||||
case MultiStatus = 207
|
||||
case Forbidden = 403
|
||||
case MethodNotAllowed = 405
|
||||
case Conflict = 409
|
||||
case PreconditionFailed = 412
|
||||
case UnsupportedMediaType = 415
|
||||
case Locked = 423
|
||||
case FailedDependency = 424
|
||||
case BadGateway = 502
|
||||
case InsufficientStorage = 507
|
||||
}
|
||||
|
||||
public struct FileProviderWebDavError: ErrorType, CustomStringConvertible {
|
||||
public let code: FileProviderWebDavErrorCode
|
||||
public let url: NSURL
|
||||
|
||||
public var description: String {
|
||||
switch code {
|
||||
case .OK: return "OK"
|
||||
case .Created: return "Created"
|
||||
case .NoContent: return "No Content"
|
||||
case .MultiStatus: return ""
|
||||
case .Forbidden: return "Forbidden"
|
||||
case .MethodNotAllowed: return "Method Not Allowed"
|
||||
case .Conflict: return "Conflict"
|
||||
case .PreconditionFailed: return "Precondition Failed"
|
||||
case .UnsupportedMediaType: return "Unsupported Media Type"
|
||||
case .Locked: return "Locked"
|
||||
case .FailedDependency: return "Failed Dependency"
|
||||
case .BadGateway: return "Bad Gateway"
|
||||
case .InsufficientStorage: return "Insufficient Storage"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final class WebDavFileObject: FileObject {
|
||||
public let contentType: String
|
||||
public let entryTag: String?
|
||||
@@ -102,12 +63,15 @@ public class WebDAVFileProvider: NSObject, FileProviderBasic {
|
||||
let url = absoluteURL(path)
|
||||
let request = NSMutableURLRequest(URL: url)
|
||||
request.HTTPMethod = "PROPFIND"
|
||||
//request.setValue(baseURL?.uw_absoluteString, forHTTPHeaderField: "Host")
|
||||
request.setValue("1", forHTTPHeaderField: "Depth")
|
||||
request.setValue("text/xml; charset=\"utf-8\"", forHTTPHeaderField: "Content-Type")
|
||||
request.HTTPBody = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<D:propfind xmlns:D=\"DAV:\">\n<D:allprop/></D:propfind>".dataUsingEncoding(NSUTF8StringEncoding)
|
||||
request.setValue(String(request.HTTPBody!.length), forHTTPHeaderField: "Content-Length")
|
||||
let task = session.dataTaskWithRequest(request) { (data, response, error) in
|
||||
var responseError: FileProviderWebDavError?
|
||||
if let code = (response as? NSHTTPURLResponse)?.statusCode where code >= 300, let rCode = FileProviderHTTPErrorCode(rawValue: code) {
|
||||
responseError = FileProviderWebDavError(code: rCode, url: url)
|
||||
}
|
||||
if let data = data {
|
||||
let xresponse = self.parseXMLResponse(data)
|
||||
var fileObjects = [WebDavFileObject]()
|
||||
@@ -117,31 +81,63 @@ public class WebDAVFileProvider: NSObject, FileProviderBasic {
|
||||
}
|
||||
fileObjects.append(self.mapToFileObject(attr))
|
||||
}
|
||||
completionHandler(contents: fileObjects, error: error)
|
||||
completionHandler(contents: fileObjects, error: responseError ?? error)
|
||||
return
|
||||
}
|
||||
completionHandler(contents: [], error: error)
|
||||
completionHandler(contents: [], error: responseError ?? error)
|
||||
}
|
||||
task.resume()
|
||||
}
|
||||
|
||||
public func attributesOfItemAtPath(path: String, completionHandler: ((attributes: FileObject?, error: ErrorType?) -> Void)) {
|
||||
let request = NSMutableURLRequest(URL: absoluteURL(path))
|
||||
let url = absoluteURL(path)
|
||||
let request = NSMutableURLRequest(URL: url)
|
||||
request.HTTPMethod = "PROPFIND"
|
||||
//request.setValue(baseURL?.uw_absoluteString, forHTTPHeaderField: "Host")
|
||||
request.setValue("1", forHTTPHeaderField: "Depth")
|
||||
request.setValue("text/xml; charset=\"utf-8\"", forHTTPHeaderField: "Content-Type")
|
||||
request.HTTPBody = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<D:propfind xmlns:D=\"DAV:\">\n<D:allprop/></D:propfind>".dataUsingEncoding(NSUTF8StringEncoding)
|
||||
request.setValue(String(request.HTTPBody!.length), forHTTPHeaderField: "Content-Length")
|
||||
let task = session.dataTaskWithRequest(request) { (data, response, error) in
|
||||
var responseError: FileProviderWebDavError?
|
||||
if let code = (response as? NSHTTPURLResponse)?.statusCode where code >= 300, let rCode = FileProviderHTTPErrorCode(rawValue: code) {
|
||||
responseError = FileProviderWebDavError(code: rCode, url: url)
|
||||
}
|
||||
if let data = data {
|
||||
let xresponse = self.parseXMLResponse(data)
|
||||
if let attr = xresponse.first {
|
||||
completionHandler(attributes: self.mapToFileObject(attr), error: error)
|
||||
completionHandler(attributes: self.mapToFileObject(attr), error: responseError ?? error)
|
||||
return
|
||||
}
|
||||
}
|
||||
completionHandler(attributes: nil, error: error)
|
||||
completionHandler(attributes: nil, error: responseError ?? error)
|
||||
}
|
||||
task.resume()
|
||||
}
|
||||
|
||||
public func storageProperties(completionHandler: ((total: Int64, used: Int64) -> Void)) {
|
||||
// Not all WebDAV clients implements RFC2518 which allows geting storage quota.
|
||||
// In this case you won't get error. totalSize is NSURLSessionTransferSizeUnknown
|
||||
// and used space is zero.
|
||||
guard let baseURL = baseURL else {
|
||||
return
|
||||
}
|
||||
let request = NSMutableURLRequest(URL: baseURL)
|
||||
request.HTTPMethod = "PROPFIND"
|
||||
request.setValue("0", forHTTPHeaderField: "Depth")
|
||||
request.setValue("text/xml; charset=\"utf-8\"", forHTTPHeaderField: "Content-Type")
|
||||
request.HTTPBody = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<D:propfind xmlns:D=\"DAV:\">\n<D:prop><D:quota-available-bytes/><D:quota-used-bytes/></D:prop>\n</D:propfind>".dataUsingEncoding(NSUTF8StringEncoding)
|
||||
request.setValue(String(request.HTTPBody!.length), forHTTPHeaderField: "Content-Length")
|
||||
let task = session.dataTaskWithRequest(request) { (data, response, error) in
|
||||
if let data = data {
|
||||
let xresponse = self.parseXMLResponse(data)
|
||||
if let attr = xresponse.first {
|
||||
let totalSize = Int64(attr.prop["quota-available-bytes"] ?? "")
|
||||
let usedSize = Int64(attr.prop["quota-used-bytes"] ?? "")
|
||||
completionHandler(total: totalSize ?? -1, used: usedSize ?? 0)
|
||||
return
|
||||
}
|
||||
}
|
||||
completionHandler(total: -1, used: 0)
|
||||
}
|
||||
task.resume()
|
||||
}
|
||||
@@ -154,24 +150,32 @@ extension WebDAVFileProvider: FileProviderOperations {
|
||||
let url = absoluteURL((atPath as NSString).stringByAppendingPathComponent(folderName) + "/")
|
||||
let request = NSMutableURLRequest(URL: url)
|
||||
request.HTTPMethod = "MKCOL"
|
||||
//request.setValue(baseURL?.uw_absoluteString, forHTTPHeaderField: "Host")
|
||||
let task = session.dataTaskWithRequest(request) { (data, response, error) in
|
||||
if let response = response as? NSHTTPURLResponse, let code = FileProviderWebDavErrorCode(rawValue: response.statusCode) where code != .OK {
|
||||
var responseError: FileProviderWebDavError?
|
||||
if let code = (response as? NSHTTPURLResponse)?.statusCode where code >= 300, let rCode = FileProviderHTTPErrorCode(rawValue: code) {
|
||||
responseError = FileProviderWebDavError(code: rCode, url: url)
|
||||
}
|
||||
if let response = response as? NSHTTPURLResponse, let code = FileProviderHTTPErrorCode(rawValue: response.statusCode) where code != .OK {
|
||||
completionHandler?(error: FileProviderWebDavError(code: code, url: url))
|
||||
return
|
||||
}
|
||||
completionHandler?(error: error)
|
||||
self.delegateNotify(.Create(path: (atPath as NSString).stringByAppendingPathComponent(folderName) + "/"), error: error)
|
||||
completionHandler?(error: responseError ?? error)
|
||||
self.delegateNotify(.Create(path: (atPath as NSString).stringByAppendingPathComponent(folderName) + "/"), error: responseError ?? error)
|
||||
}
|
||||
task.resume()
|
||||
}
|
||||
|
||||
public func createFile(fileAttribs: FileObject, atPath path: String, contents data: NSData?, completionHandler: SimpleCompletionHandler) {
|
||||
let request = NSMutableURLRequest(URL: absoluteURL(path))
|
||||
let url = absoluteURL(path)
|
||||
let request = NSMutableURLRequest(URL: url)
|
||||
request.HTTPMethod = "PUT"
|
||||
let task = session.uploadTaskWithRequest(request, fromData: data) { (data, response, error) in
|
||||
completionHandler?(error: error)
|
||||
self.delegateNotify(.Create(path: (path as NSString).stringByAppendingPathComponent(fileAttribs.name)), error: error)
|
||||
var responseError: FileProviderWebDavError?
|
||||
if let code = (response as? NSHTTPURLResponse)?.statusCode where code >= 300, let rCode = FileProviderHTTPErrorCode(rawValue: code) {
|
||||
responseError = FileProviderWebDavError(code: rCode, url: url)
|
||||
}
|
||||
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.resume()
|
||||
@@ -193,13 +197,12 @@ extension WebDAVFileProvider: FileProviderOperations {
|
||||
} else {
|
||||
request.HTTPMethod = "COPY"
|
||||
}
|
||||
//request.setValue(baseURL?.uw_absoluteString, forHTTPHeaderField: "Host")
|
||||
request.setValue(absoluteURL(path).uw_absoluteString, forHTTPHeaderField: "Destination")
|
||||
if !overwrite {
|
||||
request.setValue("F", forHTTPHeaderField: "Overwrite")
|
||||
}
|
||||
let task = session.dataTaskWithRequest(request) { (data, response, error) in
|
||||
if let response = response as? NSHTTPURLResponse, let code = FileProviderWebDavErrorCode(rawValue: response.statusCode) {
|
||||
if let response = response as? NSHTTPURLResponse, let code = FileProviderHTTPErrorCode(rawValue: response.statusCode) {
|
||||
defer {
|
||||
let op = move ? FileOperation.Move(source: path, destination: toPath) : .Copy(source: path, destination: toPath)
|
||||
self.delegateNotify(op, error: error)
|
||||
@@ -223,9 +226,8 @@ extension WebDAVFileProvider: FileProviderOperations {
|
||||
let url = absoluteURL(path)
|
||||
let request = NSMutableURLRequest(URL: url)
|
||||
request.HTTPMethod = "DELETE"
|
||||
//request.setValue(baseURL?.uw_absoluteString, forHTTPHeaderField: "Host")
|
||||
let task = session.dataTaskWithRequest(request) { (data, response, error) in
|
||||
if let response = response as? NSHTTPURLResponse, let code = FileProviderWebDavErrorCode(rawValue: response.statusCode) {
|
||||
if let response = response as? NSHTTPURLResponse, let code = FileProviderHTTPErrorCode(rawValue: response.statusCode) {
|
||||
defer {
|
||||
self.delegateNotify(.Remove(path: path), error: error)
|
||||
}
|
||||
@@ -245,19 +247,29 @@ extension WebDAVFileProvider: FileProviderOperations {
|
||||
}
|
||||
|
||||
public func copyLocalFileToPath(localFile: NSURL, toPath: String, completionHandler: SimpleCompletionHandler) {
|
||||
let request = NSMutableURLRequest(URL: absoluteURL(toPath))
|
||||
let url = absoluteURL(toPath)
|
||||
let request = NSMutableURLRequest(URL: url)
|
||||
request.HTTPMethod = "PUT"
|
||||
let task = session.uploadTaskWithRequest(request, fromFile: localFile) { (data, response, error) in
|
||||
completionHandler?(error: error)
|
||||
self.delegateNotify(.Move(source: localFile.uw_absoluteString, destination: toPath), error: error)
|
||||
var responseError: FileProviderWebDavError?
|
||||
if let code = (response as? NSHTTPURLResponse)?.statusCode where code >= 300, let rCode = FileProviderHTTPErrorCode(rawValue: code) {
|
||||
responseError = FileProviderWebDavError(code: rCode, url: url)
|
||||
}
|
||||
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.resume()
|
||||
}
|
||||
|
||||
public func copyPathToLocalFile(path: String, toLocalURL: NSURL, completionHandler: SimpleCompletionHandler) {
|
||||
let request = NSMutableURLRequest(URL: absoluteURL(path))
|
||||
let url = absoluteURL(path)
|
||||
let request = NSMutableURLRequest(URL: url)
|
||||
let task = session.downloadTaskWithRequest(request) { (sourceFileURL, response, error) in
|
||||
var responseError: FileProviderWebDavError?
|
||||
if let code = (response as? NSHTTPURLResponse)?.statusCode where code >= 300, let rCode = FileProviderHTTPErrorCode(rawValue: code) {
|
||||
responseError = FileProviderWebDavError(code: rCode, url: url)
|
||||
}
|
||||
if let sourceFileURL = sourceFileURL {
|
||||
do {
|
||||
try NSFileManager.defaultManager().copyItemAtURL(sourceFileURL, toURL: toLocalURL)
|
||||
@@ -266,7 +278,7 @@ extension WebDAVFileProvider: FileProviderOperations {
|
||||
return
|
||||
}
|
||||
}
|
||||
completionHandler?(error: error)
|
||||
completionHandler?(error: responseError ?? error)
|
||||
}
|
||||
task.taskDescription = self.dictionaryToJSON(["type": "Copy", "source": path, "dest": toLocalURL.uw_absoluteString])
|
||||
task.resume()
|
||||
@@ -279,7 +291,8 @@ extension WebDAVFileProvider: FileProviderReadWrite {
|
||||
}
|
||||
|
||||
public func contentsAtPath(path: String, offset: Int64, length: Int, completionHandler: ((contents: NSData?, error: ErrorType?) -> Void)) {
|
||||
let request = NSMutableURLRequest(URL: absoluteURL(path))
|
||||
let url = absoluteURL(path)
|
||||
let request = NSMutableURLRequest(URL: url)
|
||||
request.HTTPMethod = "GET"
|
||||
if length > 0 {
|
||||
request.setValue("bytes=\(offset)-\(offset + length)", forHTTPHeaderField: "Range")
|
||||
@@ -287,7 +300,11 @@ extension WebDAVFileProvider: FileProviderReadWrite {
|
||||
request.setValue("bytes=\(offset)-", forHTTPHeaderField: "Range")
|
||||
}
|
||||
let task = session.dataTaskWithRequest(request) { (data, response, error) in
|
||||
completionHandler(contents: data, error: error)
|
||||
var responseError: FileProviderWebDavError?
|
||||
if let code = (response as? NSHTTPURLResponse)?.statusCode where code >= 300, let rCode = FileProviderHTTPErrorCode(rawValue: code) {
|
||||
responseError = FileProviderWebDavError(code: rCode, url: url)
|
||||
}
|
||||
completionHandler(contents: data, error: responseError ?? error)
|
||||
}
|
||||
task.resume()
|
||||
}
|
||||
@@ -298,16 +315,20 @@ extension WebDAVFileProvider: FileProviderReadWrite {
|
||||
let request = NSMutableURLRequest(URL: url)
|
||||
request.HTTPMethod = "PUT"
|
||||
let task = session.uploadTaskWithRequest(request, fromData: data) { (data, response, error) in
|
||||
var responseError: FileProviderWebDavError?
|
||||
if let code = (response as? NSHTTPURLResponse)?.statusCode where code >= 300, let rCode = FileProviderHTTPErrorCode(rawValue: code) {
|
||||
responseError = FileProviderWebDavError(code: rCode, url: self.absoluteURL(path))
|
||||
}
|
||||
defer {
|
||||
self.delegateNotify(.Modify(path: path), error: error)
|
||||
self.delegateNotify(.Modify(path: path), error: responseError ?? error)
|
||||
}
|
||||
if let error = error {
|
||||
completionHandler?(error: error)
|
||||
return
|
||||
}
|
||||
if atomically {
|
||||
self.moveItemAtPath((path as NSString).stringByAppendingPathExtension("tmp")!, toPath: path, completionHandler: completionHandler)
|
||||
}
|
||||
if let error = error {
|
||||
// If there is no error, completionHandler has been executed by move command
|
||||
completionHandler?(error: error)
|
||||
}
|
||||
}
|
||||
task.taskDescription = self.dictionaryToJSON(["type": "Modify", "source": path])
|
||||
task.resume()
|
||||
@@ -317,13 +338,16 @@ extension WebDAVFileProvider: FileProviderReadWrite {
|
||||
let url = absoluteURL(path)
|
||||
let request = NSMutableURLRequest(URL: url)
|
||||
request.HTTPMethod = "PROPFIND"
|
||||
//request.setValue(baseURL?.uw_absoluteString, forHTTPHeaderField: "Host")
|
||||
//request.setValue("1", forHTTPHeaderField: "Depth")
|
||||
request.setValue("text/xml; charset=\"utf-8\"", forHTTPHeaderField: "Content-Type")
|
||||
request.HTTPBody = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<D:propfind xmlns:D=\"DAV:\">\n<D:allprop/></D:propfind>".dataUsingEncoding(NSUTF8StringEncoding)
|
||||
request.setValue(String(request.HTTPBody!.length), forHTTPHeaderField: "Content-Length")
|
||||
let task = session.dataTaskWithRequest(request) { (data, response, error) in
|
||||
// FIXME: paginating results
|
||||
var responseError: FileProviderWebDavError?
|
||||
if let code = (response as? NSHTTPURLResponse)?.statusCode where code >= 300, let rCode = FileProviderHTTPErrorCode(rawValue: code) {
|
||||
responseError = FileProviderWebDavError(code: rCode, url: url)
|
||||
}
|
||||
if let data = data {
|
||||
let xresponse = self.parseXMLResponse(data)
|
||||
var fileObjects = [WebDavFileObject]()
|
||||
@@ -335,10 +359,10 @@ extension WebDAVFileProvider: FileProviderReadWrite {
|
||||
fileObjects.append(fileObject)
|
||||
foundItemHandler?(fileObject)
|
||||
}
|
||||
completionHandler(files: fileObjects, error: error)
|
||||
completionHandler(files: fileObjects, error: responseError ?? error)
|
||||
return
|
||||
}
|
||||
completionHandler(files: [], error: error)
|
||||
completionHandler(files: [], error: responseError ?? error)
|
||||
}
|
||||
task.resume()
|
||||
}
|
||||
@@ -508,10 +532,155 @@ extension WebDAVFileProvider: NSURLSessionDataDelegate, NSURLSessionDownloadDele
|
||||
}
|
||||
|
||||
public func URLSession(session: NSURLSession, task: NSURLSessionTask, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
|
||||
completionHandler(NSURLSessionAuthChallengeDisposition.UseCredential, credential)
|
||||
let deposition: NSURLSessionAuthChallengeDisposition = credential != nil ? .UseCredential : .PerformDefaultHandling
|
||||
completionHandler(deposition, credential)
|
||||
}
|
||||
|
||||
public func URLSession(session: NSURLSession, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
|
||||
completionHandler(NSURLSessionAuthChallengeDisposition.UseCredential, credential)
|
||||
let deposition: NSURLSessionAuthChallengeDisposition = credential != nil ? .UseCredential : .PerformDefaultHandling
|
||||
completionHandler(deposition, credential)
|
||||
}
|
||||
}
|
||||
|
||||
public struct FileProviderWebDavError: ErrorType, CustomStringConvertible {
|
||||
public let code: FileProviderHTTPErrorCode
|
||||
public let url: NSURL
|
||||
|
||||
public var description: String {
|
||||
return code.description
|
||||
}
|
||||
}
|
||||
|
||||
public enum FileProviderHTTPErrorCode: Int {
|
||||
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 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 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 NotExtended = 510
|
||||
case NetworkAuthenticationRequired = 511
|
||||
|
||||
public var description: String {
|
||||
switch self.rawValue {
|
||||
case 100: return "Continue"
|
||||
case 101: return "Switching Protocols"
|
||||
case 102: return "Processing"
|
||||
case 200: return "OK"
|
||||
case 201: return "Created"
|
||||
case 202: return "Accepted"
|
||||
case 203: return "Non-Authoritative Information"
|
||||
case 204: return "No Content"
|
||||
case 205: return "Reset Content"
|
||||
case 206: return "Partial Content"
|
||||
case 207: return "Multi-Status"
|
||||
case 208: return "Already Reported"
|
||||
case 226: return "IM Used"
|
||||
case 300: return "Multiple Choices"
|
||||
case 301: return "Moved Permanently"
|
||||
case 302: return "Found"
|
||||
case 303: return "See Other"
|
||||
case 304: return "Not Modified"
|
||||
case 305: return "Use Proxy"
|
||||
case 307: return "Temporary Redirect"
|
||||
case 308: return "Permanent Redirect"
|
||||
case 400: return "Bad Request"
|
||||
case 401: return "Unauthorized/Expired Session"
|
||||
case 402: return "Payment Required"
|
||||
case 403: return "Forbidden"
|
||||
case 404: return "Not Found"
|
||||
case 405: return "Method Not Allowed"
|
||||
case 406: return "Not Acceptable"
|
||||
case 407: return "Proxy Authentication Required"
|
||||
case 408: return "Request Timeout"
|
||||
case 409: return "Conflict"
|
||||
case 410: return "Gone"
|
||||
case 411: return "Length Required"
|
||||
case 412: return "Precondition Failed"
|
||||
case 413: return "Payload Too Large"
|
||||
case 414: return "URI Too Long"
|
||||
case 415: return "Unsupported Media Type"
|
||||
case 416: return "Range Not Satisfiable"
|
||||
case 417: return "Expectation Failed"
|
||||
case 421: return "Misdirected Request"
|
||||
case 422: return "Unprocessable Entity"
|
||||
case 423: return "Locked"
|
||||
case 424: return "Failed Dependency"
|
||||
case 426: return "Upgrade Required"
|
||||
case 428: return "Precondition Required"
|
||||
case 429: return "Too Many Requests"
|
||||
case 431: return "Request Header Fields Too Large"
|
||||
case 451: return "Unavailable For Legal Reasons"
|
||||
case 500: return "Internal Server Error"
|
||||
case 501: return "Not Implemented"
|
||||
case 502: return "Bad Gateway"
|
||||
case 503: return "Service Unavailable"
|
||||
case 504: return "Gateway Timeout"
|
||||
case 505: return "HTTP Version Not Supported"
|
||||
case 506: return "Variant Also Negotiates"
|
||||
case 507: return "Insufficient Storage"
|
||||
case 508: return "Loop Detected"
|
||||
case 510: return "Not Extended"
|
||||
case 511: return "Network Authentication Required"
|
||||
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