Implemented SMB.ChangeNotify command, syntax fixed

This commit is contained in:
Amir Abbas Mousavian
2016-08-08 15:57:08 +04:30
parent c4049b961f
commit 33be492499
6 changed files with 340 additions and 189 deletions
+16
View File
@@ -7,6 +7,12 @@
objects = {
/* Begin PBXBuildFile section */
794C21FE1D58912A00EC49B8 /* DropboxHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 794C21FD1D58912A00EC49B8 /* DropboxHelper.swift */; };
794C21FF1D58912A00EC49B8 /* DropboxHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 794C21FD1D58912A00EC49B8 /* DropboxHelper.swift */; };
794C22001D58912A00EC49B8 /* DropboxHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 794C21FD1D58912A00EC49B8 /* DropboxHelper.swift */; };
794C220A1D5893F800EC49B8 /* SMB2Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 794C22091D5893F800EC49B8 /* SMB2Notification.swift */; };
794C220B1D5893F800EC49B8 /* SMB2Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 794C22091D5893F800EC49B8 /* SMB2Notification.swift */; };
794C220C1D5893F800EC49B8 /* SMB2Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 794C22091D5893F800EC49B8 /* SMB2Notification.swift */; };
799396A71D48C02300086753 /* AEXML.swift in Sources */ = {isa = PBXBuildFile; fileRef = 799396921D48C02300086753 /* AEXML.swift */; };
799396A81D48C02300086753 /* AEXML.swift in Sources */ = {isa = PBXBuildFile; fileRef = 799396921D48C02300086753 /* AEXML.swift */; };
799396A91D48C02300086753 /* AEXML.swift in Sources */ = {isa = PBXBuildFile; fileRef = 799396921D48C02300086753 /* AEXML.swift */; };
@@ -67,6 +73,8 @@
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
794C21FD1D58912A00EC49B8 /* DropboxHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DropboxHelper.swift; sourceTree = "<group>"; };
794C22091D5893F800EC49B8 /* SMB2Notification.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SMB2Notification.swift; sourceTree = "<group>"; };
799396671D48B7F600086753 /* FileProvider.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = FileProvider.framework; sourceTree = BUILT_PRODUCTS_DIR; };
799396751D48B80D00086753 /* FileProvider.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = FileProvider.framework; sourceTree = BUILT_PRODUCTS_DIR; };
799396821D48B82700086753 /* FileProvider.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = FileProvider.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -155,6 +163,7 @@
799396991D48C02300086753 /* SMBTypes */,
799396921D48C02300086753 /* AEXML.swift */,
799396931D48C02300086753 /* DropboxFileProvider.swift */,
794C21FD1D58912A00EC49B8 /* DropboxHelper.swift */,
799396941D48C02300086753 /* FileProvider.h */,
799396951D48C02300086753 /* FileProvider.swift */,
799396961D48C02300086753 /* LocalFileProvider.swift */,
@@ -179,6 +188,7 @@
7993969C1D48C02300086753 /* SMB2FileHandle.swift */,
7993969E1D48C02300086753 /* SMB2IOCtl.swift */,
7993969F1D48C02300086753 /* SMB2Query.swift */,
794C22091D5893F800EC49B8 /* SMB2Notification.swift */,
799396A11D48C02300086753 /* SMB2SetInfo.swift */,
);
path = SMBTypes;
@@ -340,7 +350,9 @@
799396C51D48C02300086753 /* SMB2FileOperation.swift in Sources */,
799396BF1D48C02300086753 /* SMB2DataTypes.swift in Sources */,
799396B91D48C02300086753 /* SMBFileProvider.swift in Sources */,
794C21FE1D58912A00EC49B8 /* DropboxHelper.swift in Sources */,
799396BC1D48C02300086753 /* CIFSTypes.swift in Sources */,
794C220A1D5893F800EC49B8 /* SMB2Notification.swift in Sources */,
799396D11D48C02300086753 /* SMB2SetInfo.swift in Sources */,
799396A71D48C02300086753 /* AEXML.swift in Sources */,
799396CE1D48C02300086753 /* SMB2Session.swift in Sources */,
@@ -366,7 +378,9 @@
799396C61D48C02300086753 /* SMB2FileOperation.swift in Sources */,
799396C01D48C02300086753 /* SMB2DataTypes.swift in Sources */,
799396BA1D48C02300086753 /* SMBFileProvider.swift in Sources */,
794C21FF1D58912A00EC49B8 /* DropboxHelper.swift in Sources */,
799396BD1D48C02300086753 /* CIFSTypes.swift in Sources */,
794C220B1D5893F800EC49B8 /* SMB2Notification.swift in Sources */,
799396D21D48C02300086753 /* SMB2SetInfo.swift in Sources */,
799396A81D48C02300086753 /* AEXML.swift in Sources */,
799396CF1D48C02300086753 /* SMB2Session.swift in Sources */,
@@ -392,7 +406,9 @@
799396C71D48C02300086753 /* SMB2FileOperation.swift in Sources */,
799396C11D48C02300086753 /* SMB2DataTypes.swift in Sources */,
799396BB1D48C02300086753 /* SMBFileProvider.swift in Sources */,
794C22001D58912A00EC49B8 /* DropboxHelper.swift in Sources */,
799396BE1D48C02300086753 /* CIFSTypes.swift in Sources */,
794C220C1D5893F800EC49B8 /* SMB2Notification.swift in Sources */,
799396D31D48C02300086753 /* SMB2SetInfo.swift in Sources */,
799396A91D48C02300086753 /* AEXML.swift in Sources */,
799396D01D48C02300086753 /* SMB2Session.swift in Sources */,
+4 -186
View File
@@ -7,28 +7,7 @@
//
import Foundation
public struct FileProviderDropboxError: ErrorType, CustomStringConvertible {
public let code: FileProviderHTTPErrorCode
public let path: String
public var description: String {
return code.description
}
}
public final class DropboxFileObject: FileObject {
public let serverTime: NSDate?
public let id: String?
public let rev: String?
public init(name: String, path: String, size: Int64 = -1, serverTime: NSDate? = nil, modifiedDate: NSDate? = nil, fileType: FileType = .Regular, isHidden: Bool = false, isReadOnly: Bool = false, id: String? = nil, rev: String? = nil) {
self.serverTime = serverTime
self.id = id
self.rev = rev
super.init(absoluteURL: NSURL(string: path), name: name, path: path, size: size, createdDate: nil, modifiedDate: modifiedDate, fileType: fileType, isHidden: isHidden, isReadOnly: isReadOnly)
}
}
import CoreGraphics
// Because this class uses NSURLSession, it's necessary to disable App Transport Security
// in case of using this class with unencrypted HTTP connection.
@@ -47,7 +26,7 @@ public class DropboxFileProvider: NSObject, FileProviderBasic {
public let credential: NSURLCredential?
private var _session: NSURLSession?
private var session: NSURLSession {
internal var session: NSURLSession {
if _session == nil {
let queue = NSOperationQueue()
//queue.underlyingQueue = dispatch_queue
@@ -299,7 +278,7 @@ extension DropboxFileProvider: FileProviderReadWrite {
extension DropboxFileProvider: ExtendedFileProvider {
public func thumbnailOfFileSupported(path: String) -> Bool {
switch path.pathExtension.lowercaseString {
switch (path as NSString).pathExtension.lowercaseString {
case "jpg", "jpeg", "gif", "bmp", "png", "tif", "tiff":
return true
/*case "doc", "docx", "docm", "xls", "xlsx", "xlsm":
@@ -319,7 +298,7 @@ extension DropboxFileProvider: ExtendedFileProvider {
public func thumbnailOfFileAtPath(path: String, dimension: CGSize, completionHandler: ((image: ImageClass?, error: ErrorType?) -> Void)) {
let url: NSURL
switch path.pathExtension.lowercaseString {
switch (path as NSString).pathExtension.lowercaseString {
case "jpg", "jpeg", "gif", "bmp", "png", "tif", "tiff":
url = NSURL(string: "https://content.dropboxapi.com/2/files/get_thumbnail")!
/*case "doc", "docx", "docm", "xls", "xlsx", "xlsm":
@@ -356,167 +335,6 @@ extension DropboxFileProvider: ExtendedFileProvider {
}
}
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, maxResults: Int = -1, 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 {
private func mapToFileObject(jsonStr: String) -> DropboxFileObject? {
guard let json = self.jsonToDictionary(jsonStr) else { return nil }
return self.mapToFileObject(json)
}
private func mapToFileObject(json: [String: AnyObject]) -> DropboxFileObject? {
guard let name = json["name"] as? String else { return nil }
guard let path = json["path_display"] as? String else { return nil }
let size = (json["size"] as? NSNumber)?.longLongValue ?? -1
let serverTime = resolveDate(json["server_modified"] as? String ?? "")
let modifiedDate = resolveDate(json["client_modified"] as? String ?? "")
let isDirectory = (json[".tag"] as? String) == "folder"
let isReadonly = (json["sharing_info"]?["read_only"] as? NSNumber)?.boolValue ?? false
let id = json["id"] as? String
let rev = json["id"] as? String
return DropboxFileObject(name: name, path: path, size: size, serverTime: serverTime, modifiedDate: modifiedDate, fileType: isDirectory ? .Directory : .Regular, isReadOnly: isReadonly, id: id, rev: rev)
}
private func delegateNotify(operation: FileOperation, error: ErrorType?) {
dispatch_async(dispatch_get_main_queue(), {
if error == nil {
self.delegate?.fileproviderSucceed(self, operation: operation)
} else {
self.delegate?.fileproviderFailed(self, operation: operation)
}
})
}
}
extension DropboxFileProvider: FileProvider {}
// MARK: URLSession delegate
+192
View File
@@ -0,0 +1,192 @@
//
// DropboxHelper.swift
// FileProvider
//
// Created by Amir Abbas Mousavian on 5/18/95.
//
//
import Foundation
public struct FileProviderDropboxError: ErrorType, CustomStringConvertible {
public let code: FileProviderHTTPErrorCode
public let path: String
public var description: String {
return code.description
}
}
public final class DropboxFileObject: FileObject {
public let serverTime: NSDate?
public let id: String?
public let rev: String?
public init(name: String, path: String, size: Int64 = -1, serverTime: NSDate? = nil, modifiedDate: NSDate? = nil, fileType: FileType = .Regular, isHidden: Bool = false, isReadOnly: Bool = false, id: String? = nil, rev: String? = nil) {
self.serverTime = serverTime
self.id = id
self.rev = rev
super.init(absoluteURL: NSURL(string: path), name: name, path: path, size: size, createdDate: nil, modifiedDate: modifiedDate, fileType: fileType, isHidden: isHidden, isReadOnly: isReadOnly)
}
}
internal extension DropboxFileProvider {
func list(path: String, cursor: String? = nil, prevContents: [DropboxFileObject] = [], recursive: Bool = false, completionHandler: ((contents: [FileObject], cursor: String?, error: ErrorType?) -> Void)) {
var requestDictionary = [String: AnyObject]()
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()
}
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, maxResults: Int = -1, 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 {
func mapToFileObject(jsonStr: String) -> DropboxFileObject? {
guard let json = self.jsonToDictionary(jsonStr) else { return nil }
return self.mapToFileObject(json)
}
func mapToFileObject(json: [String: AnyObject]) -> DropboxFileObject? {
guard let name = json["name"] as? String else { return nil }
guard let path = json["path_display"] as? String else { return nil }
let size = (json["size"] as? NSNumber)?.longLongValue ?? -1
let serverTime = resolveDate(json["server_modified"] as? String ?? "")
let modifiedDate = resolveDate(json["client_modified"] as? String ?? "")
let isDirectory = (json[".tag"] as? String) == "folder"
let isReadonly = (json["sharing_info"]?["read_only"] as? NSNumber)?.boolValue ?? false
let id = json["id"] as? String
let rev = json["id"] as? String
return DropboxFileObject(name: name, path: path, size: size, serverTime: serverTime, modifiedDate: modifiedDate, fileType: isDirectory ? .Directory : .Regular, isReadOnly: isReadonly, id: id, rev: rev)
}
func delegateNotify(operation: FileOperation, error: ErrorType?) {
dispatch_async(dispatch_get_main_queue(), {
if error == nil {
self.delegate?.fileproviderSucceed(self, operation: operation)
} else {
self.delegate?.fileproviderFailed(self, operation: operation)
}
})
}
}
+127
View File
@@ -0,0 +1,127 @@
//
// SMB2Notification.swift
// FileProvider
//
// Created by Amir Abbas Mousavian on 5/18/95.
//
//
import Foundation
extension SMB2 {
// MARK: SMB2 Change Notify
struct ChangeNotifyRequest: SMBRequest {
let size: UInt16
let flags: ChangeNotifyRequest.Flags
let outputBufferLength: UInt32
let fileId: FileId
let completionFilters: CompletionFilter
private let reserved: UInt32
init(fileId: FileId, completionFilters: CompletionFilter, flags: ChangeNotifyRequest.Flags = [], outputBufferLength: UInt32 = 65535) {
self.size = 32
self.flags = flags
self.outputBufferLength = outputBufferLength
self.fileId = fileId
self.completionFilters = completionFilters
self.reserved = 0
}
func data() -> NSData {
return encode(self)
}
struct Flags: OptionSetType {
let rawValue: UInt16
init(rawValue: UInt16) {
self.rawValue = rawValue
}
static let WATCH_TREE = Flags(rawValue: 0x0001)
}
struct CompletionFilter: OptionSetType {
let rawValue: UInt32
init(rawValue: UInt32) {
self.rawValue = rawValue
}
static let FILE_NAME = Flags(rawValue: 0x00000001)
static let DIR_NAME = Flags(rawValue: 0x00000002)
static let ATTRIBUTES = Flags(rawValue: 0x00000004)
static let SIZE = Flags(rawValue: 0x00000008)
static let LAST_WRITE = Flags(rawValue: 0x00000010)
static let LAST_ACCESS = Flags(rawValue: 0x00000020)
static let CREATION = Flags(rawValue: 0x00000040)
static let EA = Flags(rawValue: 0x00000080)
static let SECURITY = Flags(rawValue: 0x00000100)
static let STREAM_NAME = Flags(rawValue: 0x00000200)
static let STREAM_SIZE = Flags(rawValue: 0x00000400)
static let STREAM_WRITE = Flags(rawValue: 0x00000800)
static let all = Flags(rawValue: 0x00000FFF)
}
}
struct ChangeNotifyResponse: SMBResponse {
let notifications: [(action: FileNotifyAction, fileName: String)]
init?(data: NSData) {
let maxLoop = 1000
var i = 0
var result = [(action: FileNotifyAction, fileName: String)]()
var offset: UInt32 = 0
while i < maxLoop {
let actionData = data.subdataWithRange(NSRange(location: Int(offset + 4), length: 4))
let actionValue: UInt32 = decode(actionData)
guard let action = FileNotifyAction(rawValue: actionValue) else {
continue
}
let fileLenData = data.subdataWithRange(NSRange(location: Int(offset + 8), length: 4))
let fileNameLen: UInt32 = decode(fileLenData)
let fileNameData = data.subdataWithRange(NSRange(location: Int(offset + 12), length: Int(12 + fileNameLen)))
let fileName = String(data: fileNameData, encoding: NSUTF16StringEncoding) ?? ""
result.append((action: action, fileName: fileName))
let nextOffsetData = data.subdataWithRange(NSRange(location: Int(offset), length: 4))
let nextOffset: UInt32 = decode(nextOffsetData)
offset += nextOffset
if nextOffset == 0 {
break
}
i += 1
}
self.notifications = result
}
}
enum FileNotifyAction: UInt32 {
/// The file was added to the directory.
case ADDED = 0x00000001
/// The file was removed from the directory.
case REMOVED = 0x00000002
/// The file was modified. This can be a change to the data or attributes of the file.
case MODIFIED = 0x00000003
/// The file was renamed, and this is the old name. If the new name resides outside of the directory being monitored, the client will not receive the FILE_ACTION_RENAMED_NEW_NAME bit value.
case RENAMED_OLD_NAME = 0x00000004
/// The file was renamed, and this is the new name. If the old name resides outside of the directory being monitored, the client will not receive the FILE_ACTION_RENAME_OLD_NAME bit value.
case RENAMED_NEW_NAME = 0x00000005
/// The file was added to a named stream.
case ADDED_STREAM = 0x00000006
/// The file was removed from the named stream.
case REMOVED_STREAM = 0x00000007
/// The file was modified. This can be a change to the data or attributes of the file.
case MODIFIED_STREAM = 0x00000008
/// An object ID was removed because the file the object ID referred to was deleted. This notification is only sent when the directory being monitored is the special directory "\$Extend\$ObjId:$O:$INDEX_ALLOCATION".
case REMOVED_BY_DELETE = 0x00000009
/// An attempt to tunnel object ID information to a file being created or renamed failed because the object ID is in use by another file on the same volume. This notification is only sent when the directory being monitored is the special directory "\$Extend\$ObjId:$O:$INDEX_ALLOCATION".
case NOT_TUNNELLED = 0x0000000A
/// An attempt to tunnel object ID information to a file being renamed failed because the file already has an object ID. This notification is only sent when the directory being monitored is the special directory "\$Extend\$ObjId:$O:$INDEX_ALLOCATION".
case TUNNELLED_ID_COLLISION = 0x0000000B
}
}
-2
View File
@@ -317,8 +317,6 @@ extension SMB2 {
UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8,
UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8)
// MARK: SMB2 Change Notify
// MARK: SMB2 Query Info
}
+1 -1
View File
@@ -60,7 +60,7 @@ extension SMB2 {
var contextCount: UInt16
private let reserved2: UInt16
var clientStartTime: SMBTime {
let time = UInt64(contextOffset) + (UInt64(contextCount) << 32) + (UInt64(contextCount) << 48)
let time = Int64(contextOffset) + (Int64(contextCount) << 32) + (Int64(contextCount) << 48)
return SMBTime(time: time)
}