Change Notifier, SMB2 Create Request/Response, Bug fix

This commit is contained in:
Amir Abbas Mousavian
2016-07-04 19:38:36 +04:30
parent 22400884f8
commit d6059fc5df
5 changed files with 294 additions and 121 deletions
+3
View File
@@ -121,6 +121,9 @@ public protocol FileProvider: class {
func writeContentsAtPath(path: String, contents data: NSData, atomically: Bool, completionHandler: SimpleCompletionHandler)
func searchFilesAtPath(path: String, recursive: Bool, query: String, foundItemHandler: ((FileObjectClass) -> Void)?, completionHandler: ((files: [FileObjectClass], error: ErrorType?) -> Void))
func registerNotifcation(path: String, eventHandler: (() -> Void))
func unregisterNotifcation(path: String)
}
extension FileProvider {
+70
View File
@@ -283,6 +283,32 @@ public class LocalFileProvider: FileProvider {
completionHandler(files: result, error: nil)
}
}
private var monitorDictionary = [String : LocalFolderMonitor]()
public func registerNotifcation(path: String, eventHandler: (() -> Void)) {
self.unregisterNotifcation(path)
var isdirv: AnyObject?
do {
try absoluteURL(path).getResourceValue(&isdirv, forKey: NSURLIsDirectoryKey)
} catch _ {
}
if !(isdirv?.boolValue ?? false) {
return
}
let monitor = LocalFolderMonitor(url: absoluteURL(path)) {
eventHandler()
}
monitor.start()
monitorDictionary[path] = monitor
}
public func unregisterNotifcation(path: String) {
if let prevMonitor = monitorDictionary[path] {
prevMonitor.stop()
monitorDictionary.removeValueForKey(path)
}
}
}
extension LocalFileProvider {
@@ -303,3 +329,47 @@ extension LocalFileProvider {
}
}
}
private class LocalFolderMonitor {
private let source: dispatch_source_t
private let descriptor: CInt
private let qq: dispatch_queue_t = dispatch_get_main_queue()
private var state: Bool = false
/// Creates a folder monitor object with monitoring enabled.
init(url: NSURL, handler: ()->Void) {
descriptor = open(url.fileSystemRepresentation, O_EVTONLY)
source = dispatch_source_create(
DISPATCH_SOURCE_TYPE_VNODE,
UInt(descriptor),
DISPATCH_VNODE_WRITE,
qq
)
dispatch_source_set_event_handler(source, handler)
start()
}
/// Starts sending notifications if currently stopped
func start() {
if !state {
state = true
dispatch_resume(source)
}
}
/// Stops sending notifications if currently enabled
func stop() {
if state {
state = false
dispatch_suspend(source)
}
}
deinit {
close(descriptor)
dispatch_source_cancel(source)
}
}
+173 -89
View File
@@ -101,7 +101,8 @@ class SMBProtocolClient: TCPSocketClient {
}
let headersize = sizeof(SMB2.Header.self)
let headerData = data.subdataWithRange(NSRange(location: 0, length: headersize))
let messageData = data.subdataWithRange(NSRange(location: headersize, length: 0))
let messageSize = data.length - headersize
let messageData = data.subdataWithRange(NSRange(location: headersize, length: messageSize))
let header: SMB2.Header = decode(headerData)
switch header.command {
case .NEGOTIATE:
@@ -145,7 +146,6 @@ class SMBProtocolClient: TCPSocketClient {
case .INVALID:
throw SMBFileProviderError.InvalidCommand
}
throw SMBFileProviderError.BadHeader
}
class func createSMBMessage(header: SMB1.Header, blocks: [(params: NSData?, message: NSData?)]) -> NSData {
@@ -643,7 +643,7 @@ struct SMB2 {
if Int(header.size) != 65 {
return nil
}
let bufOffset = Int(self.header.bufferOffset)
let bufOffset = Int(self.header.bufferOffset) - sizeof(SMB2.Header.self)
let bufLen = Int(self.header.bufferLength)
if bufOffset > 0 && bufLen > 0 && data.length >= bufOffset + bufLen {
self.buffer = data.subdataWithRange(NSRange(location: bufOffset, length: bufLen))
@@ -651,7 +651,7 @@ struct SMB2 {
self.buffer = nil
}
let contextCount = Int(self.header.contextCount)
let contextOffset = Int(self.header.contextOffset)
let contextOffset = Int(self.header.contextOffset) - sizeof(SMB2.Header.self)
if contextCount > 0 && contextOffset > 0 {
// TODO: NegotiateResponse context support for SMB3
self.contexts = []
@@ -726,7 +726,7 @@ struct SMB2 {
func data() -> NSData {
var header = self.header
header.bufferOffset = UInt16(sizeofValue(header))
header.bufferOffset = UInt16(sizeof(SMB2.Header.self) + sizeof(SessionSetupRequest.Header.self))
header.bufferLength = UInt16(buffer?.length ?? 0)
let result = NSMutableData(data: encode(&header))
if let buffer = self.buffer {
@@ -782,7 +782,7 @@ struct SMB2 {
if Int(header.size) != 9 {
return nil
}
let bufOffset = Int(self.header.bufferOffset)
let bufOffset = Int(self.header.bufferOffset) - sizeof(SMB2.Header.self)
let bufLen = Int(self.header.bufferLength)
if bufOffset > 0 && bufLen > 0 && data.length >= bufOffset + bufLen {
self.buffer = data.subdataWithRange(NSRange(location: bufOffset, length: bufLen))
@@ -866,7 +866,7 @@ struct SMB2 {
func data() -> NSData {
var header = self.header
header.pathOffset = UInt16(sizeofValue(header))
header.pathOffset = UInt16(sizeof(SMB2.Header.self) + sizeof(TreeConnectRequest.Header.self))
header.pathLength = UInt16(buffer?.length ?? 0)
let result = NSMutableData(data: encode(&header))
if let buffer = self.buffer {
@@ -988,10 +988,36 @@ struct SMB2 {
struct CreateRequest: SMBRequest {
let header: CreateRequest.Header
let name: String?
let contexts: [CreateContext]
init (header: CreateRequest.Header, name: String? = nil, contexts: [CreateContext] = []) {
self.header = header
self.name = name
self.contexts = contexts
}
func data() -> NSData {
return NSData()
var header = self.header
var offset = 0x78 //UInt16(sizeof(SMB2.Header.self) + sizeof(CreateContext.Header.self) - 1)
let body = NSMutableData()
if let name = self.name, let nameData = name.dataUsingEncoding(NSUTF8StringEncoding) {
header.nameOffset = UInt16(offset)
header.nameLength = UInt16(nameData.length)
offset += nameData.length
body.appendData(nameData)
}
if contexts.count > 0 {
// TODO: Context CreateRequest implementation, 8 bit allign offset
header.contextOffset = UInt32(offset)
header.contextLength = 0
//result.appendData(nameData)
}
let result = NSMutableData(data: encode(&header))
result.appendData(body)
return result
}
struct Header {
@@ -1030,66 +1056,27 @@ struct SMB2 {
}
}
let options: CreateOptions
var nameOffset: UInt16
var nameLength: UInt16
var contextOffset: UInt32
var contextLength: UInt32
}
struct CreateContext: SMBRequest, SMBResponse {
var next: UInt32
let nameOffset: UInt16
let nameLength: UInt16
private let reserved: UInt16
let dataOffset: UInt16
let dataLength: UInt32
let buffer: NSData
init(name: ContextNames, data: NSData) {
init(requestedOplockLevel: OplockLevel = .NONE, impersonationLevel: ImpersonationLevel = .Anonymous, access: FileAccessMask = [.GENERIC_ALL], fileAttributes: FileAttributes = [], shareAccess: ShareAccess = [.READ], desposition: CreateDisposition = .OPEN_IF, options: CreateOptions = []) {
self.size = 57
self.securityFlags = 0
self._requestedOplockLevel = requestedOplockLevel.rawValue
self._impersonationLevel = impersonationLevel.rawValue
self.flags = 0
self.reserved = 0
self.next = 0
self.nameOffset = 32
let result = NSMutableData(data: (name.rawValue).dataUsingEncoding(NSUTF8StringEncoding)!)
self.nameLength = UInt16(result.length)
self.dataOffset = UInt16(result.length)
self.dataLength = UInt32(data.length)
result.appendData(data)
buffer = result
}
init(name: NSUUID, data: NSData) {
self.reserved = 0
self.next = 0
self.nameOffset = 32
var uuid = uuid_t(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
name.getUUIDBytes(&uuid.0)
let result = NSMutableData(bytes: &uuid, length: 16)
self.nameLength = UInt16(result.length)
self.dataOffset = UInt16(result.length)
self.dataLength = UInt32(data.length)
result.appendData(data)
buffer = result
}
init? (data: NSData) {
return nil
}
func data() -> NSData {
return NSData()
}
enum ContextNames: String {
/// Extended attributes
case EA_BUFFER = "ExtA"
/// Security descriptor
case SD_BUFFER = "SecD"
/// Requesting the open to be durable
case DURABLE_HANDLE_REQUEST = "DHnQ"
/// Requesting to reconnect to a durable open after being disconnected
case DURABLE_HANDLE_RECONNECT = "DHnC"
/// Required allocation size of the newly created file
case ALLOCATION_SIZE = "AISi"
case QUERY_MAXIMAL_ACCESS_REQUEST = "MxAc"
case TIMEWARP_TOKEN = "TWrp"
self.access = access
self.fileAttributes = fileAttributes
self.shareAccess = shareAccess
self._desposition = desposition.rawValue
self.options = options
self.nameOffset = 0
self.nameLength = 0
self.contextOffset = 0
self.contextLength = 0
}
}
@@ -1147,31 +1134,133 @@ struct SMB2 {
}
struct CreateResponse: SMBResponse {
let size: UInt16
private let _oplockLevel: UInt8
var oplockLevel: OplockLevel {
return OplockLevel(rawValue: _oplockLevel)!
struct Header {
let size: UInt16
private let _oplockLevel: UInt8
var oplockLevel: OplockLevel {
return OplockLevel(rawValue: _oplockLevel)!
}
private let reserved: UInt32
let creationTime: SMBTime
let lastAccessTime: SMBTime
let lastWriteTime: SMBTime
let changeTime: SMBTime
let allocationSize: UInt64
let endOfFile: UInt64
let fileAttributes: FileAttributes
private let reserved2: UInt32
let fileIdPersistent: UInt64
let fileIdVolatile: UInt64
let contextsOffset: UInt32
let ContextsLength: UInt32
}
private let reserved: UInt32
let creationTime: SMBTime
let lastAccessTime: SMBTime
let lastWriteTime: SMBTime
let changeTime: SMBTime
let allocationSize: UInt64
let endOfFile: UInt64
let fileAttributes: FileAttributes
let header: CreateResponse.Header
let contexts: [CreateContext]
init? (data: NSData) {
self = decode(data)
guard data.length >= sizeof(CreateResponse.Header.self) else {
return nil
}
let headerData = data.subdataWithRange(NSRange(location: 0, length: sizeof(CreateResponse.Header.self)))
self.header = decode(headerData)
if self.header.contextsOffset > 0 {
var contexts = [CreateContext]()
var contextOffset = Int(self.header.contextsOffset) - sizeof(SMB2.Header.self)
while contextOffset > 0 {
guard contextOffset < data.length else {
self.contexts = contexts
return
}
let contextDataHeader = data.subdataWithRange(NSRange(location: contextOffset, length: sizeof(CreateContext.Header.self)))
if let lastContextHeader = CreateContext(data: contextDataHeader) {
let lastContextLen = Int(lastContextHeader.header.dataOffset) + Int(lastContextHeader.header.dataLength) - contextOffset
let lastContextData = data.subdataWithRange(NSRange(location: contextOffset, length: lastContextLen))
if let newContext = CreateContext(data: lastContextData) {
contexts.append(newContext)
}
contextOffset = Int(lastContextHeader.header.next) - sizeof(SMB2.Header.self)
}
}
self.contexts = contexts
} else {
self.contexts = []
}
}
}
struct CreateContext {
struct Header {
var next: UInt32
let nameOffset: UInt16
let nameLength: UInt16
private let reserved: UInt16
let dataOffset: UInt16
let dataLength: UInt32
}
var header: CreateContext.Header
let buffer: NSData
init(name: ContextNames, data: NSData) {
let nameData = NSMutableData(data: (name.rawValue).dataUsingEncoding(NSUTF8StringEncoding)!)
self.header = CreateContext.Header(next: 0, nameOffset: 32, nameLength: UInt16(nameData.length), reserved: 0, dataOffset: UInt16(nameData.length), dataLength: UInt32(data.length))
self.buffer = data
}
init(name: NSUUID, data: NSData) {
var uuid = uuid_t(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
name.getUUIDBytes(&uuid.0)
let nameData = NSMutableData(bytes: &uuid, length: 16)
self.header = CreateContext.Header(next: 0, nameOffset: 32, nameLength: UInt16(nameData.length), reserved: 0, dataOffset: UInt16(nameData.length), dataLength: UInt32(data.length))
self.buffer = data
}
init? (data: NSData) {
let headersize = sizeof(Header)
guard data.length > headersize else {
return nil
}
let headerData = data.subdataWithRange(NSRange(location: 0, length: headersize))
self.header = decode(headerData)
self.buffer = data.subdataWithRange(NSRange(location: headersize, length: data.length - headersize))
}
func data() -> NSData {
var header = self.header
let result = NSMutableData(data: encode(&header))
result.appendData(buffer)
return result
}
enum ContextNames: String {
/// Request Create Context: Extended attributes
case EA_BUFFER = "ExtA"
/// Request Create Context: Security descriptor
case SD_BUFFER = "SecD"
/// Request & Response Create Context: Open to be durable
case DURABLE_HANDLE = "DHnQ"
case DURABLE_HANDLE_RESPONSE_V2 = "DH2Q"
/// Request Create Context: Reconnect to a durable open after being disconnected
case DURABLE_HANDLE_RECONNECT = "DHnC"
/// Request Create Context: Required allocation size of the newly created file
case ALLOCATION_SIZE = "AISi"
/// Request & Response Create Context: Maximal access information
case QUERY_MAXIMAL_ACCESS = "MxAc"
case TIMEWARP_TOKEN = "TWrp"
/// Response Create Context: DiskID of the open file in a volume.
case QUERY_ON_DISK_ID = "QFid"
/// Response Create Context: A lease. This value is only supported for the SMB 2.1 and 3.x dialect family.
case LEASE = "RqLs"
}
}
enum OplockLevel: UInt8 {
case LEVEL_NONE = 0x00
case NONE = 0x00
case LEVEL_II = 0x01
case LEVEL_EXCLUSIVE = 0x08
case LEVEL_BATCH = 0x09
case LEVEL_LEASE = 0xFF
case EXCLUSIVE = 0x08
case BATCH = 0x09
case LEASE = 0xFF
}
struct ShareAccess: OptionSetType {
@@ -1340,12 +1429,7 @@ struct SMB2 {
// MARK: SMB2 Lock
// MARK: SMB2 IOCTL
/*
* Device-Platform specific operations, which is defferent from system to system
* Should not be implemented in a general SMB client
*/
// MARK: SMB2 Cancel
struct CancelRequest: SMBRequest {
+9
View File
@@ -96,6 +96,15 @@ class SMBFileProvider: FileProvider {
func searchFilesAtPath(path: String, recursive: Bool, query: String, foundItemHandler: ((FileObjectClass) -> Void)?, completionHandler: ((files: [FileObjectClass], error: ErrorType?) -> Void)) {
NotImplemented()
}
func registerNotifcation(path: String, eventHandler: (() -> Void)) {
NotImplemented()
}
func unregisterNotifcation(path: String) {
NotImplemented()
}
}
// MARK: basic CIFS interactivity
+39 -32
View File
@@ -8,7 +8,7 @@
import Foundation
enum FileProviderWebDavErrorCode: Int {
public enum FileProviderWebDavErrorCode: Int {
case OK = 200
case Created = 201
case NoContent = 204
@@ -24,11 +24,11 @@ enum FileProviderWebDavErrorCode: Int {
case InsufficientStorage = 507
}
struct FileProviderWebDavError: ErrorType, CustomStringConvertible {
public struct FileProviderWebDavError: ErrorType, CustomStringConvertible {
let code: FileProviderWebDavErrorCode
let url: NSURL
var description: String {
public var description: String {
switch code {
case .OK: return "OK"
case .Created: return "Created"
@@ -47,7 +47,7 @@ struct FileProviderWebDavError: ErrorType, CustomStringConvertible {
}
}
final class WebDavFileObject: FileObject {
public final class WebDavFileObject: FileObject {
let contentType: String
let entryTag: String?
@@ -61,16 +61,16 @@ final class WebDavFileObject: FileObject {
// Because this class uses NSURLSession, it's necessary to disable App Transport Security
// in case of using this class with unencrypted HTTP connection.
class WebDAVFileProvider: NSObject, FileProvider {
let type: String = "WebDAV"
let isPathRelative: Bool = true
let baseURL: NSURL?
var currentPath: String = ""
var dispatch_queue: dispatch_queue_t
var delegate: FileProviderDelegate?
let credential: NSURLCredential?
public class WebDAVFileProvider: NSObject, FileProvider {
public let type: String = "WebDAV"
public let isPathRelative: Bool = true
public let baseURL: NSURL?
public var currentPath: String = ""
public var dispatch_queue: dispatch_queue_t
public var delegate: FileProviderDelegate?
public let credential: NSURLCredential?
typealias FileObjectClass = FileObject
public typealias FileObjectClass = FileObject
private var _session: NSURLSession?
private var session: NSURLSession {
@@ -93,7 +93,7 @@ class WebDAVFileProvider: NSObject, FileProvider {
deinit {
}
func contentsOfDirectoryAtPath(path: String, completionHandler: ((contents: [FileObjectClass], error: ErrorType?) -> Void)) {
public func contentsOfDirectoryAtPath(path: String, completionHandler: ((contents: [FileObjectClass], error: ErrorType?) -> Void)) {
let url = absoluteURL(path)
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "PROPFIND"
@@ -129,7 +129,7 @@ class WebDAVFileProvider: NSObject, FileProvider {
task.resume()
}
func attributesOfItemAtPath(path: String, completionHandler: ((attributes: FileObjectClass?, error: ErrorType?) -> Void)) {
public func attributesOfItemAtPath(path: String, completionHandler: ((attributes: FileObjectClass?, error: ErrorType?) -> Void)) {
let request = NSMutableURLRequest(URL: absoluteURL(path))
request.HTTPMethod = "PROPFIND"
request.setValue(baseURL?.absoluteString, forHTTPHeaderField: "Host")
@@ -159,7 +159,7 @@ class WebDAVFileProvider: NSObject, FileProvider {
task.resume()
}
func createFolder(folderName: String, atPath: String, completionHandler: SimpleCompletionHandler) {
public func createFolder(folderName: String, atPath: String, completionHandler: SimpleCompletionHandler) {
let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
let url = absoluteURL(atPath.stringByAppendingPathComponent(folderName) + "/")
let request = NSMutableURLRequest(URL: url)
@@ -182,7 +182,7 @@ class WebDAVFileProvider: NSObject, FileProvider {
task.resume()
}
func createFile(fileAttribs: FileObject, atPath path: String, contents data: NSData?, completionHandler: SimpleCompletionHandler) {
public func createFile(fileAttribs: FileObject, atPath path: String, contents data: NSData?, completionHandler: SimpleCompletionHandler) {
let request = NSMutableURLRequest(URL: absoluteURL(path))
request.HTTPMethod = "PUT"
let task = session.uploadTaskWithRequest(request, fromData: data) { (data, response, error) in
@@ -199,7 +199,7 @@ class WebDAVFileProvider: NSObject, FileProvider {
task.resume()
}
func moveItemAtPath(path: String, toPath: String, overwrite: Bool = false, completionHandler: SimpleCompletionHandler) {
public func moveItemAtPath(path: String, toPath: String, overwrite: Bool = false, completionHandler: SimpleCompletionHandler) {
let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
let url = absoluteURL(path)
let request = NSMutableURLRequest(URL: url)
@@ -237,7 +237,7 @@ class WebDAVFileProvider: NSObject, FileProvider {
task.resume()
}
func copyItemAtPath(path: String, toPath: String, overwrite: Bool = false, completionHandler: SimpleCompletionHandler) {
public func copyItemAtPath(path: String, toPath: String, overwrite: Bool = false, completionHandler: SimpleCompletionHandler) {
let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
let url = absoluteURL(path)
let request = NSMutableURLRequest(URL: url)
@@ -275,7 +275,7 @@ class WebDAVFileProvider: NSObject, FileProvider {
task.resume()
}
func removeItemAtPath(path: String, completionHandler: SimpleCompletionHandler) {
public func removeItemAtPath(path: String, completionHandler: SimpleCompletionHandler) {
let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
let url = absoluteURL(path)
let request = NSMutableURLRequest(URL: url)
@@ -309,7 +309,7 @@ class WebDAVFileProvider: NSObject, FileProvider {
task.resume()
}
func copyLocalFileToPath(localFile: NSURL, toPath: String, completionHandler: SimpleCompletionHandler) {
public func copyLocalFileToPath(localFile: NSURL, toPath: String, completionHandler: SimpleCompletionHandler) {
let request = NSMutableURLRequest(URL: absoluteURL(toPath))
request.HTTPMethod = "PUT"
let task = session.uploadTaskWithRequest(request, fromFile: localFile) { (data, response, error) in
@@ -326,7 +326,7 @@ class WebDAVFileProvider: NSObject, FileProvider {
task.resume()
}
func copyPathToLocalFile(path: String, toLocalURL: NSURL, completionHandler: SimpleCompletionHandler) {
public func copyPathToLocalFile(path: String, toLocalURL: NSURL, completionHandler: SimpleCompletionHandler) {
let request = NSMutableURLRequest(URL: absoluteURL(path))
let task = session.downloadTaskWithRequest(request) { (sourceFileURL, response, error) in
if let sourceFileURL = sourceFileURL {
@@ -343,7 +343,7 @@ class WebDAVFileProvider: NSObject, FileProvider {
task.resume()
}
func contentsAtPath(path: String, completionHandler: ((contents: NSData?, error: ErrorType?) -> Void)) {
public func contentsAtPath(path: String, completionHandler: ((contents: NSData?, error: ErrorType?) -> Void)) {
let request = NSMutableURLRequest(URL: absoluteURL(path))
request.HTTPMethod = "GET"
let task = session.dataTaskWithRequest(request) { (data, response, error) in
@@ -352,7 +352,7 @@ class WebDAVFileProvider: NSObject, FileProvider {
task.resume()
}
func contentsAtPath(path: String, offset: Int64, length: Int, completionHandler: ((contents: NSData?, error: ErrorType?) -> Void)) {
public func contentsAtPath(path: String, offset: Int64, length: Int, completionHandler: ((contents: NSData?, error: ErrorType?) -> Void)) {
let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
let request = NSMutableURLRequest(URL: absoluteURL(path))
request.HTTPMethod = "GET"
@@ -363,7 +363,7 @@ class WebDAVFileProvider: NSObject, FileProvider {
task.resume()
}
func writeContentsAtPath(path: String, contents data: NSData, atomically: Bool = false, completionHandler: SimpleCompletionHandler) {
public func writeContentsAtPath(path: String, contents data: NSData, atomically: Bool = false, completionHandler: SimpleCompletionHandler) {
// FIXME: lock destination before writing process
let url = atomically ? absoluteURL(path).URLByAppendingPathExtension("tmp") : absoluteURL(path)
let request = NSMutableURLRequest(URL: url)
@@ -390,7 +390,7 @@ class WebDAVFileProvider: NSObject, FileProvider {
task.resume()
}
func searchFilesAtPath(path: String, recursive: Bool, query: String, foundItemHandler: ((FileObjectClass) -> Void)?, completionHandler: ((files: [FileObjectClass], error: ErrorType?) -> Void)) {
public func searchFilesAtPath(path: String, recursive: Bool, query: String, foundItemHandler: ((FileObjectClass) -> Void)?, completionHandler: ((files: [FileObjectClass], error: ErrorType?) -> Void)) {
let url = absoluteURL(path)
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "PROPFIND"
@@ -427,12 +427,19 @@ class WebDAVFileProvider: NSObject, FileProvider {
}
task.resume()
}
public func registerNotifcation(path: String, eventHandler: (() -> Void)) {
NotImplemented()
}
public func unregisterNotifcation(path: String) {
NotImplemented()
}
// TODO: implements methods for lock mechanism
}
// MARK: WEBDAV XML response implementation
extension WebDAVFileProvider {
internal extension WebDAVFileProvider {
struct DavResponse {
let href: NSURL
let status: Int?
@@ -531,11 +538,11 @@ extension WebDAVFileProvider {
// MARK: URLSession delegate
extension WebDAVFileProvider: NSURLSessionDataDelegate, NSURLSessionDownloadDelegate {
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) {
public func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) {
return
}
func URLSession(session: NSURLSession, task: NSURLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
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
}
@@ -569,7 +576,7 @@ extension WebDAVFileProvider: NSURLSessionDataDelegate, NSURLSessionDownloadDele
self.delegate?.fileproviderProgress(self, operation: op, progress: progress)
}
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
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
}
@@ -577,11 +584,11 @@ extension WebDAVFileProvider: NSURLSessionDataDelegate, NSURLSessionDownloadDele
self.delegate?.fileproviderProgress(self, operation: .Copy(source: source, destination: dest), progress: Float(totalBytesWritten) / Float(totalBytesExpectedToWrite))
}
func URLSession(session: NSURLSession, task: NSURLSessionTask, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
public func URLSession(session: NSURLSession, task: NSURLSessionTask, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
completionHandler(NSURLSessionAuthChallengeDisposition.UseCredential, credential)
}
func URLSession(session: NSURLSession, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
public func URLSession(session: NSURLSession, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
completionHandler(NSURLSessionAuthChallengeDisposition.UseCredential, credential)
}
}