Compare commits

...

15 Commits

Author SHA1 Message Date
Amir Abbas 47885c0a4e Deprecated FileObject.fileType with .type 2016-12-09 21:06:11 +03:30
Alek Slater ac44aa190f Overwrite param added to copyItem + minor bugfix and improvements (#18)
- Added overwrite param to copyItem from local to remote
- fixed an issue with file upload on dropbox that wouldnt work for people in non UTC timezones.
- made filebased upload for dropbox not read file data into memory let URLSession stream from the disk instead
2016-12-09 20:58:50 +03:30
Amir Abbas 50f6a393a0 Compiler Optimizations, Dropbox readme 2016-12-09 19:07:46 +03:30
Amir Abbas 779b38f381 Default values implemented in protocol level 2016-12-09 10:04:41 +03:30
Amir Abbas a374841883 Refined SPM/manual installation guide in Readme 2016-12-08 20:41:52 +03:30
Amir Abbas 0123d8b117 Overwrite option to writeContents 2016-12-07 21:24:19 +03:30
Amir Abbas Mousavian fdc4bb818d Merge pull request #17 from skela/master
Added overwrite option to DropboxProvider.writeContents()
2016-12-07 20:13:17 +03:30
Amir Abbas Mousavian a08a9fe7a0 Updated semantics
and changed default overwrite value to false
2016-12-07 20:12:15 +03:30
Alek Slater 792ac6b015 Update DropboxFileProvider.swift
Exposes the overwrite parameter for writeContents in DropboxFileProvider
2016-12-07 11:27:51 +08:00
Amir Abbas 8bad5944bc Updated pod spec version to 0.8.1 2016-12-07 02:36:49 +03:30
Amir Abbas 6ef2ab11c4 Fixed bug in Data(value:) initializer. Switch uuid init via this 2016-12-07 02:34:34 +03:30
Amir Abbas Mousavian 7f27d46c70 Merge pull request #16 from RndmTsk/master
Fixes #15, FileObject.fileType always returns nil.
2016-12-07 02:29:28 +03:30
Terry Latanville b1ec99b1b8 Fixes #15, FileObject.fileType always returns nil. 2016-12-06 17:18:41 -05:00
Amir Abbas Mousavian c4b8065cd3 Merge pull request #14 from skela/master
Update DropboxFileProvider.swift
2016-12-06 10:51:58 +03:30
Alek Slater 2d8454c711 Update DropboxFileProvider.swift
Using the same request dict creation method that can be found in the contents method, to avoid error when trying to use copyItem to copy a remote file to a local file destination.
2016-12-06 14:51:48 +08:00
13 changed files with 162 additions and 85 deletions
+1 -1
View File
@@ -16,7 +16,7 @@ Pod::Spec.new do |s|
#
s.name = "FileProvider"
s.version = "0.8.0"
s.version = "0.8.2"
s.summary = "FileManager replacement for Local and Remote (WebDAV/Dropbox/SMB2) files on iOS and macOS."
# This description is used to generate tags and improve search results.
+2 -2
View File
@@ -565,7 +565,7 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
APPLICATION_EXTENSION_API_ONLY = YES;
BUNDLE_VERSION_STRING = 0.8.0;
BUNDLE_VERSION_STRING = 0.8.2;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
@@ -618,7 +618,7 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
APPLICATION_EXTENSION_API_ONLY = YES;
BUNDLE_VERSION_STRING = 0.8.0;
BUNDLE_VERSION_STRING = 0.8.2;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
+13 -8
View File
@@ -43,21 +43,26 @@ Legacy version is available in swift-2 branch
### Cocoapods / Carthage / Swift Package Manager
FileProvider supports both CocoaPods.
Add this line to your pods file:
```ruby
pod "FileProvider"
```
Or add this to cartfile:
Or add this to Cartfile:
```
github "amosavian/FileProvider"
```
### Git
Or to use in Swift Package Manager add this line in `Dependencies`:
```swift
.Package(url: "https://github.com/amosavian/FileProvider.git", majorVersion: 0, minorVersion: 8)
```
### Manually
To have latest updates with ease, use this command on terminal to get a clone:
```bash
@@ -75,11 +80,11 @@ if you have a git based project, use this command in your projects directory to
```bash
git submodule add https://github.com/amosavian/FileProvider
```
Then you can do either:
### Manually
**First way:** Copy Source folder to your project and Voila!
* Copy Source folder to your project and Voila!
**Second way:** Drop FileProvider.xcodeproj to you Xcode workspace and add the framework to your Embeded Binaries in target.
* Drop FileProvider.xcodeproj to you Xcode workspace and add the framework to your Embeded Binaries in target.
## Usage
@@ -112,7 +117,7 @@ let webdavProvider = WebDAVFileProvider(baseURL: URL(string: "http://www.example
* In case you want to connect non-secure servers for WebDAV (http) in iOS 9+ / macOS 10.11+ you should disable App Transport Security (ATS) according to [this guide.](https://gist.github.com/mlynch/284699d676fe9ed0abfa)
* For Dropbox, user is clientID and password is Token which both must be retrieved via [OAuth2 API of Dropbox](https://www.dropbox.com/developers/reference/oauth-guide). There are libraries like [p2/OAuth2](https://github.com/p2/OAuth2) or [OAuthSwift](https://github.com/OAuthSwift/OAuthSwift) which can facilate the procedure to retrieve token.
* For Dropbox, user is clientID and password is Token which both must be retrieved via [OAuth2 API of Dropbox](https://www.dropbox.com/developers/reference/oauth-guide). There are libraries like [p2/OAuth2](https://github.com/p2/OAuth2) or [OAuthSwift](https://github.com/OAuthSwift/OAuthSwift) which can facilate the procedure to retrieve token. The latter is easier to use and prefered.
For interaction with UI, set delegate variable of `FileProvider` object
+11 -19
View File
@@ -118,11 +118,11 @@ extension DropboxFileProvider: FileProviderOperations {
return self.writeContents(path: filePath, contents: data ?? Data(), completionHandler: completionHandler)
}
public func moveItem(path: String, to toPath: String, overwrite: Bool = false, completionHandler: SimpleCompletionHandler) -> OperationHandle? {
public func moveItem(path: String, to toPath: String, overwrite: Bool, completionHandler: SimpleCompletionHandler) -> OperationHandle? {
return doOperation(.move(source: path, destination: toPath), completionHandler: completionHandler)
}
public func copyItem(path: String, to toPath: String, overwrite: Bool = false, completionHandler: SimpleCompletionHandler) -> OperationHandle? {
public func copyItem(path: String, to toPath: String, overwrite: Bool, completionHandler: SimpleCompletionHandler) -> OperationHandle? {
return doOperation(.copy(source: path, destination: toPath), completionHandler: completionHandler)
}
@@ -174,17 +174,12 @@ extension DropboxFileProvider: FileProviderOperations {
return RemoteOperationHandle(operationType: operation, tasks: [task])
}
public func copyItem(localFile: URL, to toPath: String, completionHandler: SimpleCompletionHandler) -> OperationHandle? {
public func copyItem(localFile: URL, to toPath: String, overwrite: Bool, completionHandler: SimpleCompletionHandler) -> OperationHandle? {
let opType = FileOperationType.copy(source: localFile.absoluteString, destination: toPath)
guard fileOperationDelegate?.fileProvider(self, shouldDoOperation: opType) ?? true == true else {
return nil
}
guard let data = try? Data(contentsOf: localFile) else {
let error = throwError(localFile.absoluteString, code: URLError.fileDoesNotExist as FoundationErrorEnum)
completionHandler?(error)
return nil
}
return upload_simple(toPath, data: data, overwrite: true, operation: opType, completionHandler: completionHandler)
return upload_simple(toPath, localFile: localFile, overwrite: overwrite, operation: opType, completionHandler: completionHandler)
}
public func copyItem(path: String, toLocalURL destURL: URL, completionHandler: SimpleCompletionHandler) -> OperationHandle? {
@@ -196,13 +191,14 @@ extension DropboxFileProvider: FileProviderOperations {
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.setValue("Bearer \(credential?.password ?? "")", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let requestDictionary = ["path": correctPath(path)! as NSString]
request.setValue(dictionaryToJSON(requestDictionary), forHTTPHeaderField: "Dropbox-API-Arg")
let requestDictionary = ["path": path]
let requestJson = dictionaryToJSON(requestDictionary as [String : AnyObject]) ?? ""
request.setValue(requestJson, forHTTPHeaderField: "Dropbox-API-Arg")
let task = session.downloadTask(with: request, completionHandler: { (cacheURL, response, error) in
guard let cacheURL = cacheURL, let httpResponse = response as? HTTPURLResponse , httpResponse.statusCode < 300 else {
let code = FileProviderHTTPErrorCode(rawValue: (response as? HTTPURLResponse)?.statusCode ?? -1)
let dbError: FileProviderDropboxError? = code != nil ? FileProviderDropboxError(code: code!, path: path, errorDescription: nil) : nil
let errorData : Data? = nil //Data(contentsOf:cacheURL) // TODO: Figure out how to get error response data for the error description
let dbError : FileProviderDropboxError? = code != nil ? FileProviderDropboxError(code: code!, path: path, errorDescription: String(data: errorData ?? Data(), encoding: .utf8)) : nil
completionHandler?(dbError ?? error)
return
}
@@ -220,10 +216,6 @@ extension DropboxFileProvider: FileProviderOperations {
}
extension DropboxFileProvider: FileProviderReadWrite {
public func contents(path: String, completionHandler: @escaping ((_ contents: Data?, _ error: Error?) -> Void)) -> OperationHandle? {
return self.contents(path: path, offset: 0, length: -1, completionHandler: completionHandler)
}
public func contents(path: String, offset: Int64, length: Int, completionHandler: @escaping ((_ contents: Data?, _ error: Error?) -> Void)) -> OperationHandle? {
let opType = FileOperationType.fetch(path: path)
let url = URL(string: "https://content.dropboxapi.com/2/files/download")!
@@ -250,13 +242,13 @@ extension DropboxFileProvider: FileProviderReadWrite {
return RemoteOperationHandle(operationType: opType, tasks: [task])
}
public func writeContents(path: String, contents data: Data, atomically: Bool = false, completionHandler: SimpleCompletionHandler) -> OperationHandle? {
public func writeContents(path: String, contents data: Data, atomically: Bool, overwrite: Bool, completionHandler: SimpleCompletionHandler) -> OperationHandle? {
let opType = FileOperationType.modify(path: path)
guard fileOperationDelegate?.fileProvider(self, shouldDoOperation: opType) ?? true == true else {
return nil
}
// FIXME: remove 150MB restriction
return upload_simple(path, data: data, overwrite: true, operation: opType, completionHandler: completionHandler)
return upload_simple(path, data: data, overwrite: overwrite, operation: opType, completionHandler: completionHandler)
}
public func searchFiles(path: String, recursive: Bool, query: String, foundItemHandler: ((FileObject) -> Void)?, completionHandler: @escaping ((_ files: [FileObject], _ error: Error?) -> Void)) {
+30 -7
View File
@@ -99,19 +99,17 @@ internal extension DropboxFileProvider {
func upload_simple(_ targetPath: String, data: Data, modifiedDate: Date = Date(), overwrite: Bool, operation: FileOperationType, completionHandler: SimpleCompletionHandler) -> OperationHandle? {
assert(data.count < 150*1024*1024, "Maximum size of allowed size to upload is 150MB")
var requestDictionary = [String: AnyObject]()
var requestDictionary = [String: Any]()
let url: URL
url = URL(string: "https://content.dropboxapi.com/2/files/upload")!
requestDictionary["path"] = correctPath(targetPath) as NSString?
requestDictionary["mode"] = (overwrite ? "overwrite" : "add") as NSString
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ssz"
requestDictionary["client_modified"] = dateFormatter.string(from: modifiedDate) as NSString
requestDictionary["client_modified"] = string(from:modifiedDate)
var request = URLRequest(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.setValue(dictionaryToJSON(requestDictionary as [String : AnyObject]), forHTTPHeaderField: "Dropbox-API-Arg")
request.httpBody = data
let task = session.uploadTask(with: request, from: data, completionHandler: { (data, response, error) in
var responseError: FileProviderDropboxError?
@@ -120,7 +118,32 @@ internal extension DropboxFileProvider {
}
completionHandler?(responseError ?? error)
self.delegateNotify(.create(path: targetPath), error: responseError ?? error)
})
})
task.taskDescription = operation.json
task.resume()
return RemoteOperationHandle(operationType: operation, tasks: [task])
}
func upload_simple(_ targetPath: String, localFile: URL, modifiedDate: Date = Date(), overwrite: Bool, operation: FileOperationType, completionHandler: SimpleCompletionHandler) -> OperationHandle? {
var requestDictionary = [String: Any]()
let url: URL
url = URL(string: "https://content.dropboxapi.com/2/files/upload")!
requestDictionary["path"] = correctPath(targetPath) as NSString?
requestDictionary["mode"] = (overwrite ? "overwrite" : "add") as NSString
requestDictionary["client_modified"] = string(from:modifiedDate)
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer \(credential?.password ?? "")", forHTTPHeaderField: "Authorization")
request.setValue("application/octet-stream", forHTTPHeaderField: "Content-Type")
request.setValue(dictionaryToJSON(requestDictionary as [String : AnyObject]), forHTTPHeaderField: "Dropbox-API-Arg")
let task = session.uploadTask(with: request, fromFile: localFile, completionHandler: { (data, response, error) in
var responseError: FileProviderDropboxError?
if let code = (response as? HTTPURLResponse)?.statusCode , code >= 300, let rCode = FileProviderHTTPErrorCode(rawValue: code) {
responseError = FileProviderDropboxError(code: rCode, path: targetPath, errorDescription: String(data: data ?? Data(), encoding: .utf8))
}
completionHandler?(responseError ?? error)
self.delegateNotify(.create(path: targetPath), error: responseError ?? error)
})
task.taskDescription = operation.json
task.resume()
return RemoteOperationHandle(operationType: operation, tasks: [task])
@@ -180,7 +203,7 @@ internal extension DropboxFileProvider {
fileObject.size = (json["size"] as? NSNumber)?.int64Value ?? -1
fileObject.serverTime = resolve(dateString: json["server_modified"] as? String ?? "")
fileObject.modifiedDate = resolve(dateString: json["client_modified"] as? String ?? "")
fileObject.fileType = (json[".tag"] as? String) == "folder" ? .directory : .regular
fileObject.type = (json[".tag"] as? String) == "folder" ? .directory : .regular
fileObject.isReadOnly = (json["sharing_info"]?["read_only"] as? NSNumber)?.boolValue ?? false
fileObject.id = json["id"] as? String
fileObject.rev = json["id"] as? String
+4 -18
View File
@@ -503,21 +503,7 @@ public protocol FPSStreamDelegate : URLSessionTaskDelegate {
@objc optional func urlSession(_ session: URLSession, streamTask: FPSStreamTask, didBecome inputStream: InputStream, outputStream: OutputStream)
}
private let ports = ["http": 80,
"https": 443,
"smb": 445,
"ftp": 21,
"sftp": 22,
"sftp": 2121,
"telnet": 23,
"pop": 110,
"smtp": 25,
"imap": 143]
private let securePorts = ["https": 443,
"smb": 445,
"sftp": 22,
"sftp": 2121,
"telnet": 992,
"pop": 995,
"smtp": 465,
"imap": 993]
private let ports: [String: Int] = ["http": 80, "https": 443, "smb": 445,"ftp": 21,"ftps": 22, "sftp": 2121,
"telnet": 23, "pop": 110, "smtp": 25, "imap": 143]
private let securePorts: [String: Int] = ["https": 443, "smb": 445, "ftps": 22, "sftp": 2121,
"telnet": 992, "pop": 995, "smtp": 465, "imap": 993]
+71 -9
View File
@@ -98,29 +98,80 @@ public protocol FileProviderOperations: FileProviderBasic {
@discardableResult
func create(file: String, at: String, contents data: Data?, completionHandler: SimpleCompletionHandler) -> OperationHandle?
@discardableResult
func moveItem(path: String, to: String, completionHandler: SimpleCompletionHandler) -> OperationHandle?
@discardableResult
func moveItem(path: String, to: String, overwrite: Bool, completionHandler: SimpleCompletionHandler) -> OperationHandle?
@discardableResult
func copyItem(path: String, to: String, completionHandler: SimpleCompletionHandler) -> OperationHandle?
@discardableResult
func copyItem(path: String, to: String, overwrite: Bool, completionHandler: SimpleCompletionHandler) -> OperationHandle?
@discardableResult
func removeItem(path: String, completionHandler: SimpleCompletionHandler) -> OperationHandle?
@discardableResult
func copyItem(localFile: URL, to: String, completionHandler: SimpleCompletionHandler) -> OperationHandle?
@discardableResult
func copyItem(localFile: URL, to: String, overwrite: Bool, completionHandler: SimpleCompletionHandler) -> OperationHandle?
@discardableResult
func copyItem(path: String, toLocalURL: URL, completionHandler: SimpleCompletionHandler) -> OperationHandle?
}
extension FileProviderOperations {
@discardableResult
public func moveItem(path: String, to: String, completionHandler: SimpleCompletionHandler) -> OperationHandle? {
return self.moveItem(path: path, to: to, overwrite: false, completionHandler: completionHandler)
}
@discardableResult
public func copyItem(localFile: URL, to: String, completionHandler: SimpleCompletionHandler) -> OperationHandle? {
return self.copyItem(localFile: localFile, to: to, overwrite: false, completionHandler: completionHandler)
}
@discardableResult
public func copyItem(path: String, to: String, completionHandler: SimpleCompletionHandler) -> OperationHandle? {
return self.copyItem(path: path, to: to, overwrite: false, completionHandler: completionHandler)
}
}
public protocol FileProviderReadWrite: FileProviderBasic {
@discardableResult
func contents(path: String, completionHandler: @escaping ((_ contents: Data?, _ error: Error?) -> Void)) -> OperationHandle?
@discardableResult
func contents(path: String, offset: Int64, length: Int, completionHandler: @escaping ((_ contents: Data?, _ error: Error?) -> Void)) -> OperationHandle?
@discardableResult
func writeContents(path: String, contents: Data, completionHandler: SimpleCompletionHandler) -> OperationHandle?
@discardableResult
func writeContents(path: String, contents: Data, atomically: Bool, completionHandler: SimpleCompletionHandler) -> OperationHandle?
@discardableResult
func writeContents(path: String, contents: Data, overwrite: Bool, completionHandler: SimpleCompletionHandler) -> OperationHandle?
@discardableResult
func writeContents(path: String, contents: Data, atomically: Bool, overwrite: Bool, completionHandler: SimpleCompletionHandler) -> OperationHandle?
func searchFiles(path: String, recursive: Bool, query: String, foundItemHandler: ((FileObject) -> Void)?, completionHandler: @escaping ((_ files: [FileObject], _ error: Error?) -> Void))
}
extension FileProviderReadWrite {
@discardableResult
public func contents(path: String, completionHandler: @escaping ((_ contents: Data?, _ error: Error?) -> Void)) -> OperationHandle?{
return self.contents(path: path, offset: 0, length: -1, completionHandler: completionHandler)
}
@discardableResult
public func writeContents(path: String, contents: Data, completionHandler: SimpleCompletionHandler) -> OperationHandle? {
return self.writeContents(path: path, contents: contents, atomically: false, overwrite: false, completionHandler: completionHandler)
}
@discardableResult
public func writeContents(path: String, contents: Data, atomically: Bool, completionHandler: SimpleCompletionHandler) -> OperationHandle? {
return self.writeContents(path: path, contents: contents, atomically: atomically, overwrite: false, completionHandler: completionHandler)
}
@discardableResult
public func writeContents(path: String, contents: Data, overwrite: Bool, completionHandler: SimpleCompletionHandler) -> OperationHandle? {
return self.writeContents(path: path, contents: contents, atomically: false, overwrite: overwrite, completionHandler: completionHandler)
}
}
public protocol FileProviderMonitor: FileProviderBasic {
func registerNotifcation(path: String, eventHandler: @escaping (() -> Void))
func unregisterNotifcation(path: String)
@@ -246,6 +297,15 @@ extension FileProviderBasic {
}
return nil
}
public func string(from date:Date) -> String {
let fm = DateFormatter()
fm.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"
fm.timeZone = TimeZone(identifier:"UTC")
fm.locale = Locale(identifier:"en_US_POSIX")
return fm.string(from:date)
}
}
public protocol ExtendedFileProvider: FileProvider {
@@ -368,18 +428,20 @@ open class FileObject {
}
}
open internal(set) var fileType: URLFileResourceType? {
open internal(set) var type: URLFileResourceType? {
get {
guard let typeString = allValues[URLResourceKey.fileResourceTypeKey.rawValue] as? String else {
return nil
}
return URLFileResourceType(rawValue: typeString)
return allValues[URLResourceKey.fileResourceTypeKey.rawValue] as? URLFileResourceType
}
set {
allValues[URLResourceKey.fileResourceTypeKey.rawValue] = newValue
}
}
@available(*, deprecated, message: "Use FileObject.type property instead.")
open var fileType: URLFileResourceType? {
return self.type
}
open internal(set) var isHidden: Bool {
get {
return allValues[URLResourceKey.isHiddenKey.rawValue] as? Bool ?? false
@@ -399,15 +461,15 @@ open class FileObject {
}
open var isDirectory: Bool {
return self.fileType == .directory
return self.type == .directory
}
open var isRegularFile: Bool {
return self.fileType == .regular
return self.type == .regular
}
open var isSymLink: Bool {
return self.fileType == .symbolicLink
return self.type == .symbolicLink
}
}
+13 -2
View File
@@ -182,7 +182,8 @@ open class LocalFileProvider: FileProvider, FileProviderMonitor {
}
@discardableResult
open func copyItem(localFile: URL, to toPath: String, completionHandler: SimpleCompletionHandler) -> OperationHandle? {
open func copyItem(localFile: URL, to toPath: String, overwrite: Bool, completionHandler: SimpleCompletionHandler) -> OperationHandle? {
// TODO: Make use of overwrite parameter
let opType = FileOperationType.copy(source: localFile.absoluteString, destination: toPath)
operation_queue.async {
do {
@@ -232,6 +233,9 @@ open class LocalFileProvider: FileProvider, FileProviderMonitor {
@discardableResult
open func contents(path: String, offset: Int64, length: Int, completionHandler: @escaping ((_ contents: Data?, _ error: Error?) -> Void)) -> OperationHandle? {
if length < 0 {
return self.contents(path: path, completionHandler: completionHandler)
}
let opType = FileOperationType.fetch(path: path)
dispatch_queue.async {
let aPath = self.absoluteURL(path).path
@@ -255,8 +259,15 @@ open class LocalFileProvider: FileProvider, FileProviderMonitor {
}
@discardableResult
open func writeContents(path: String, contents data: Data, atomically: Bool, completionHandler: SimpleCompletionHandler) -> OperationHandle? {
open func writeContents(path: String, contents data: Data, atomically: Bool, overwrite: Bool, completionHandler: SimpleCompletionHandler) -> OperationHandle? {
let opType = FileOperationType.modify(path: path)
var options: Data.WritingOptions = []
if atomically {
options.insert(.atomic)
}
if overwrite {
options.insert(.withoutOverwriting)
}
operation_queue.async {
try? data.write(to: self.absoluteURL(path), options: atomically ? [.atomic] : [])
DispatchQueue.main.async(execute: {
+5 -5
View File
@@ -201,11 +201,11 @@ public enum FileProviderHTTPErrorCode: Int {
case notExtended = 510
case networkAuthenticationRequired = 511
fileprivate static let status1xx = [100: "Continue", 101: "Switching Protocols", 102: "Processing"]
fileprivate 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"]
fileprivate 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"]
fileprivate 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"]
fileprivate 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"]
fileprivate static let status1xx: [Int: String] = [100: "Continue", 101: "Switching Protocols", 102: "Processing"]
fileprivate static let status2xx: [Int: String] = [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"]
fileprivate static let status3xx: [Int: String] = [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"]
fileprivate static let status4xx: [Int: String] = [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"]
fileprivate static let status5xx: [Int: String] = [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 {
+2 -2
View File
@@ -68,7 +68,7 @@ class SMBFileProvider: FileProvider, FileProviderMonitor {
return nil
}
open func copyItem(localFile: URL, to toPath: String, completionHandler: SimpleCompletionHandler) -> OperationHandle? {
open func copyItem(localFile: URL, to toPath: String, overwrite: Bool, completionHandler: SimpleCompletionHandler) -> OperationHandle? {
NotImplemented()
return nil
}
@@ -88,7 +88,7 @@ class SMBFileProvider: FileProvider, FileProviderMonitor {
return nil
}
open func writeContents(path: String, contents data: Data, atomically: Bool, completionHandler: SimpleCompletionHandler) -> OperationHandle? {
open func writeContents(path: String, contents data: Data, atomically: Bool, overwrite: Bool, completionHandler: SimpleCompletionHandler) -> OperationHandle? {
NotImplemented()
return nil
}
+2 -3
View File
@@ -227,9 +227,8 @@ extension SMB2 {
}
init(name: UUID, data: Data) {
var uuid = uuid_t(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
(name as NSUUID).getBytes(&uuid.0)
var nameData = Data(bytes: &uuid.0, count: 16)
let uuid = name.uuid
var nameData = Data(value: uuid)
self.header = CreateContext.Header(next: 0, nameOffset: 32, nameLength: UInt16(nameData.count), reserved: 0, dataOffset: UInt16(nameData.count), dataLength: UInt32(data.count))
self.buffer = data
}
+1 -1
View File
@@ -11,7 +11,7 @@ import Foundation
extension Data {
init<T>(value: T) {
var value = value
self = Data(buffer: UnsafeBufferPointer(start: &value, count: MemoryLayout.size(ofValue: value)))
self = Data(buffer: UnsafeBufferPointer(start: &value, count: 1))
}
func scanValue<T>() -> T? {
+7 -8
View File
@@ -280,7 +280,8 @@ extension WebDAVFileProvider: FileProviderOperations {
}
@discardableResult
public func copyItem(localFile: URL, to toPath: String, completionHandler: SimpleCompletionHandler) -> OperationHandle? {
public func copyItem(localFile: URL, to toPath: String, overwrite: Bool, completionHandler: SimpleCompletionHandler) -> OperationHandle? {
// TODO: Make use of overwrite parameter
let opType = FileOperationType.copy(source: localFile.absoluteString, destination: toPath)
guard fileOperationDelegate?.fileProvider(self, shouldDoOperation: opType) ?? true == true else {
return nil
@@ -332,11 +333,6 @@ extension WebDAVFileProvider: FileProviderOperations {
}
extension WebDAVFileProvider: FileProviderReadWrite {
@discardableResult
public func contents(path: String, completionHandler: @escaping ((_ contents: Data?, _ error: Error?) -> Void)) -> OperationHandle? {
return self.contents(path: path, offset: 0, length: -1, completionHandler: completionHandler)
}
@discardableResult
public func contents(path: String, offset: Int64, length: Int, completionHandler: @escaping ((_ contents: Data?, _ error: Error?) -> Void)) -> OperationHandle? {
let opType = FileOperationType.fetch(path: path)
@@ -360,7 +356,7 @@ extension WebDAVFileProvider: FileProviderReadWrite {
}
@discardableResult
public func writeContents(path: String, contents data: Data, atomically: Bool = false, completionHandler: SimpleCompletionHandler) -> OperationHandle? {
public func writeContents(path: String, contents data: Data, atomically: Bool, overwrite: Bool, completionHandler: SimpleCompletionHandler) -> OperationHandle? {
let opType = FileOperationType.modify(path: path)
guard fileOperationDelegate?.fileProvider(self, shouldDoOperation: opType) ?? true == true else {
return nil
@@ -369,6 +365,9 @@ extension WebDAVFileProvider: FileProviderReadWrite {
let url = atomically ? absoluteURL(path).appendingPathExtension("tmp") : absoluteURL(path)
var request = URLRequest(url: url)
request.httpMethod = "PUT"
if !overwrite {
request.setValue("F", forHTTPHeaderField: "Overwrite")
}
let task = session.uploadTask(with: request, from: data, completionHandler: { (data, response, error) in
var responseError: FileProviderWebDavError?
if let code = (response as? HTTPURLResponse)?.statusCode , code >= 300, let rCode = FileProviderHTTPErrorCode(rawValue: code) {
@@ -540,7 +539,7 @@ internal extension WebDAVFileProvider {
fileObject.creationDate = self.resolve(dateString: davResponse.prop["creationdate"] ?? "")
fileObject.modifiedDate = self.resolve(dateString: davResponse.prop["getlastmodified"] ?? "")
fileObject.contentType = davResponse.prop["getcontenttype"] ?? "octet/stream"
fileObject.fileType = fileObject.contentType == "httpd/unix-directory" ? .directory : .regular
fileObject.type = fileObject.contentType == "httpd/unix-directory" ? .directory : .regular
fileObject.entryTag = davResponse.prop["getetag"]
return fileObject
}