Guest User

Untitled

a guest
May 7th, 2019
46
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.47 KB | None | 0 0
  1. import Foundation
  2. import NetFS
  3.  
  4. enum ShareMountError: Error {
  5. case InvalidURL
  6. case MountpointInaccessible
  7. case InvalidMountOptions
  8. }
  9.  
  10. enum MountOption {
  11. case NoBrowse
  12. case ReadOnly
  13. case AllowSubMounts
  14. case SoftMount
  15. case MountAtMountDirectory
  16.  
  17. case Guest
  18. case AllowLoopback
  19. case NoAuthDialog
  20. case AllowAuthDialog
  21. case ForceAuthDialog
  22. }
  23.  
  24. typealias NetFSMountCallback = (Int32, UnsafeMutableRawPointer?, CFArray?) -> Void
  25. typealias MountCallbackHandler = (Int32, URL?, [String]?) -> Void;
  26.  
  27. protocol ShareDelegate {
  28. func shareWillMount(url: URL) -> Void
  29. func shareDidMount(url: URL, at paths: [String]?) -> Void
  30. func shareMountingDidFail(for url: URL, withError: Int32) -> Void
  31. }
  32.  
  33. fileprivate func processOptionsForNetFS(options: [MountOption]) throws -> (NSMutableDictionary, NSMutableDictionary) {
  34. let openOptions: NSMutableDictionary = NSMutableDictionary()
  35. let mountOptions: NSMutableDictionary = NSMutableDictionary()
  36.  
  37. for opt in options {
  38. switch opt {
  39.  
  40. // mount_options
  41. case .NoBrowse:
  42. if let existingValue = mountOptions.value(forKey: kNetFSMountFlagsKey) {
  43. mountOptions[kNetFSMountFlagsKey] = existingValue as! Int32 | MNT_DONTBROWSE
  44. } else {
  45. mountOptions[kNetFSMountFlagsKey] = MNT_DONTBROWSE
  46. }
  47. case .ReadOnly:
  48. if let existingValue = mountOptions.value(forKey: kNetFSMountFlagsKey) {
  49. mountOptions[kNetFSMountFlagsKey] = existingValue as! Int32 | MNT_RDONLY
  50. } else {
  51. mountOptions[kNetFSMountFlagsKey] = MNT_RDONLY
  52. }
  53. case .AllowSubMounts:
  54. mountOptions[kNetFSAllowSubMountsKey] = true
  55. case .SoftMount:
  56. mountOptions[kNetFSSoftMountKey] = true
  57. case .MountAtMountDirectory:
  58. mountOptions[kNetFSMountAtMountDirKey] = true
  59.  
  60. // open_options
  61. case .Guest:
  62. openOptions[kNetFSUseGuestKey] = true
  63. case .AllowLoopback:
  64. openOptions[kNetFSAllowLoopbackKey] = true
  65. case .NoAuthDialog:
  66. openOptions[kNAUIOptionKey] = kNAUIOptionNoUI
  67. case .AllowAuthDialog:
  68. openOptions[kNAUIOptionKey] = kNAUIOptionAllowUI
  69. case .ForceAuthDialog:
  70. openOptions[kNAUIOptionKey] = kNAUIOptionForceUI
  71. }
  72. }
  73.  
  74. return (openOptions, mountOptions)
  75. }
  76.  
  77.  
  78. class Share {
  79. let url: URL
  80. var mountPoint: String = "/Volumes"
  81. var username: String?
  82. var password: String?
  83. fileprivate var asyncRequestId: AsyncRequestID?
  84. public var delegate: ShareDelegate?
  85.  
  86. init(_ url: URL) {
  87. self.url = url
  88. }
  89.  
  90. init(_ urlString: String) throws {
  91. guard let url = URL(string: urlString) else {
  92. throw ShareMountError.InvalidURL
  93. }
  94.  
  95. self.url = url
  96. }
  97.  
  98. public func cancelMounting() {
  99. NetFSMountURLCancel(self.asyncRequestId)
  100. }
  101.  
  102. static func cancelMounting(id requestId: AsyncRequestID) {
  103. NetFSMountURLCancel(requestId)
  104. }
  105.  
  106. public func mount() throws {
  107. let mountDirectoryURL = URL(fileURLWithPath: self.mountPoint)
  108. let operationQueue = OperationQueue.main
  109.  
  110. let mountReportBlock: NetFSMountCallback = {
  111. status, asyncRequestId, mountedDirs in
  112.  
  113. let mountedDirectories = mountedDirs as! [String]? ?? nil
  114.  
  115. if (status != 0) {
  116. self.delegate?.shareMountingDidFail(for: self.url, withError: status)
  117. } else {
  118. self.delegate?.shareDidMount(url: self.url, at: mountedDirectories)
  119. }
  120. }
  121.  
  122. NetFSMountURLAsync(url as CFURL,
  123. mountDirectoryURL as CFURL,
  124. username as CFString?,
  125. password as CFString?,
  126. nil,
  127. nil,
  128. &self.asyncRequestId,
  129. operationQueue.underlyingQueue,
  130. mountReportBlock)
  131. self.delegate?.shareWillMount(url: url)
  132. }
  133.  
  134. public func mount(options: [MountOption]?, callbackHandler: @escaping MountCallbackHandler) throws -> AsyncRequestID? {
  135. let mountDirectoryURL = URL(fileURLWithPath: self.mountPoint)
  136. let operationQueue = OperationQueue.main
  137.  
  138. let mountReportBlock: NetFSMountCallback = {
  139. (status, asyncRequestId, mountedDirs) in
  140. callbackHandler(status, self.url, mountedDirs as? [String])
  141. }
  142.  
  143. var openOptions: NSMutableDictionary
  144. var mountOptions: NSMutableDictionary
  145.  
  146. if options != nil {
  147. (openOptions, mountOptions) = try processOptionsForNetFS(options: options!)
  148. } else {
  149. openOptions = NSMutableDictionary()
  150. mountOptions = NSMutableDictionary()
  151. }
  152.  
  153. NetFSMountURLAsync(url as CFURL,
  154. mountDirectoryURL as CFURL,
  155. username as CFString?,
  156. password as CFString?,
  157. openOptions as CFMutableDictionary,
  158. mountOptions as CFMutableDictionary,
  159. &self.asyncRequestId,
  160. operationQueue.underlyingQueue,
  161. mountReportBlock)
  162. self.delegate?.shareWillMount(url: url)
  163. return self.asyncRequestId
  164. }
  165. }
Add Comment
Please, Sign In to add comment