NCCommunication.swift 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. //
  2. // NCCommunication.swift
  3. // Nextcloud
  4. //
  5. // Created by Marino Faggiana on 12/10/19.
  6. // Copyright © 2018 Marino Faggiana. All rights reserved.
  7. //
  8. // Author Marino Faggiana <marino.faggiana@nextcloud.com>
  9. //
  10. // This program is free software: you can redistribute it and/or modify
  11. // it under the terms of the GNU General Public License as published by
  12. // the Free Software Foundation, either version 3 of the License, or
  13. // (at your option) any later version.
  14. //
  15. // This program is distributed in the hope that it will be useful,
  16. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. // GNU General Public License for more details.
  19. //
  20. // You should have received a copy of the GNU General Public License
  21. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. //
  23. import Foundation
  24. import Alamofire
  25. import SwiftyXMLParser
  26. class NCCommunication: NSObject {
  27. @objc static let sharedInstance: NCCommunication = {
  28. let instance = NCCommunication()
  29. return instance
  30. }()
  31. //MARK: - webDAV
  32. @objc func createFolder(serverUrl: String, fileName: String ,user: String, password: String, userAgent: String, completionHandler: @escaping (_ error: Error?) -> Void) {
  33. // url
  34. var serverUrl = serverUrl
  35. var url: URLConvertible
  36. do {
  37. if serverUrl.last == "/" {
  38. serverUrl = serverUrl + fileName
  39. } else {
  40. serverUrl = serverUrl + "/" + fileName
  41. }
  42. try url = serverUrl.asURL()
  43. } catch let error {
  44. completionHandler(error)
  45. return
  46. }
  47. }
  48. @objc func readFolder(serverUrl: String, user: String, password: String, depth: String, userAgent: String, completionHandler: @escaping (_ result: [NCFile], _ error: Error?) -> Void) {
  49. var files = [NCFile]()
  50. let dataFile =
  51. """
  52. <?xml version=\"1.0\" encoding=\"UTF-8\"?>
  53. <d:propfind xmlns:d=\"DAV:\" xmlns:oc=\"http://owncloud.org/ns\" xmlns:nc=\"http://nextcloud.org/ns\">
  54. <d:prop>"
  55. <d:displayname/>
  56. <d:getcontenttype/>
  57. <d:resourcetype/>
  58. <d:getcontentlength/>
  59. <d:getlastmodified/>
  60. <d:creationdate/>
  61. <d:getetag/>
  62. <d:quota-used-bytes/>
  63. <d:quota-available-bytes/>
  64. <permissions xmlns=\"http://owncloud.org/ns\"/>
  65. <id xmlns=\"http://owncloud.org/ns\"/>
  66. <fileid xmlns=\"http://owncloud.org/ns\"/>
  67. <size xmlns=\"http://owncloud.org/ns\"/>
  68. <favorite xmlns=\"http://owncloud.org/ns\"/>
  69. <is-encrypted xmlns=\"http://nextcloud.org/ns\"/>
  70. <mount-type xmlns=\"http://nextcloud.org/ns\"/>
  71. <owner-id xmlns=\"http://owncloud.org/ns\"/>
  72. <owner-display-name xmlns=\"http://owncloud.org/ns\"/>
  73. <comments-unread xmlns=\"http://owncloud.org/ns\"/>
  74. <has-preview xmlns=\"http://nextcloud.org/ns\"/>
  75. <trashbin-filename xmlns=\"http://nextcloud.org/ns\"/>
  76. <trashbin-original-location xmlns=\"http://nextcloud.org/ns\"/>
  77. <trashbin-deletion-time xmlns=\"http://nextcloud.org/ns\"/>"
  78. </d:prop>
  79. </d:propfind>
  80. """
  81. // url
  82. var url: URLConvertible
  83. do {
  84. try url = serverUrl.asURL()
  85. } catch let error {
  86. completionHandler(files, error)
  87. return
  88. }
  89. // Headers
  90. var headers: HTTPHeaders = [.authorization(username: user, password: password)]
  91. headers.update(.userAgent(userAgent))
  92. headers.update(.contentType("application/xml"))
  93. headers.update(name: "Depth", value: depth)
  94. // Parameters
  95. //let parameters: Parameters = ["":"<?xml version=\"1.0\" encoding=\"UTF-8\"?><d:propfind xmlns:d=\"DAV:\" xmlns:oc=\"http://owncloud.org/ns\" xmlns:nc=\"http://nextcloud.org/ns\"><d:prop>" + NCResourceList + "</d:prop></d:propfind>"]
  96. // Method
  97. let method = HTTPMethod(rawValue: "PROPFIND")
  98. AF.request(url, method: method, parameters:[:], encoding: URLEncoding.httpBody, headers: headers, interceptor: nil).validate(statusCode: 200..<300).responseData { (response) in
  99. switch response.result {
  100. case.failure(let error):
  101. completionHandler(files, error)
  102. case .success( _):
  103. if let data = response.data {
  104. let xml = XML.parse(data)
  105. let elements = xml["d:multistatus", "d:response"]
  106. for element in elements {
  107. let file = NCFile()
  108. if let href = element["d:href"].text {
  109. file.path = href.removingPercentEncoding ?? ""
  110. }
  111. let propstat = element["d:propstat"][0]
  112. if let getetag = propstat["d:prop", "d:getetag"].text {
  113. file.etag = getetag.replacingOccurrences(of: "\"", with: "")
  114. }
  115. if let getlastmodified = propstat["d:prop", "d:getlastmodified"].text {
  116. if let date = NCCommunicationCommon.sharedInstance.convertDate(getlastmodified, format: "EEE, dd MMM y HH:mm:ss zzz") {
  117. file.date = date
  118. }
  119. }
  120. if let quotaavailablebytes = propstat["d:prop", "d:quota-available-bytes"].text {
  121. file.quotaAvailableBytes = Double(quotaavailablebytes) ?? 0
  122. }
  123. if let quotausedbytes = propstat["d:prop", "d:quota-used-bytes"].text {
  124. file.quotaUsedBytes = Double(quotausedbytes) ?? 0
  125. }
  126. files.append(file)
  127. }
  128. }
  129. completionHandler(files, nil)
  130. }
  131. }
  132. }
  133. //MARK: - Download
  134. @objc func download(serverUrl: String, fileName: String, fileNamePathDestination: String, user: String, password: String, userAgent: String, completionHandler: @escaping (_ error: Error?) -> Void) {
  135. // url
  136. var serverUrl = serverUrl
  137. var url: URLConvertible
  138. do {
  139. if serverUrl.last == "/" {
  140. serverUrl = serverUrl + fileName
  141. } else {
  142. serverUrl = serverUrl + "/" + fileName
  143. }
  144. try url = serverUrl.asURL()
  145. } catch let error {
  146. completionHandler(error)
  147. return
  148. }
  149. // Destination
  150. var destination: Alamofire.DownloadRequest.Destination?
  151. if let fileNamePathDestinationURL = URL(string: fileNamePathDestination) {
  152. let destinationFile: DownloadRequest.Destination = { _, _ in
  153. return (fileNamePathDestinationURL, [.removePreviousFile, .createIntermediateDirectories])
  154. }
  155. destination = destinationFile
  156. }
  157. // Headers
  158. var headers: HTTPHeaders = [.authorization(username: user, password: password)]
  159. headers.update(.userAgent(userAgent))
  160. AF.download(url, method: .get, parameters: nil, encoding: URLEncoding.default, headers: headers, interceptor: nil, to: destination).downloadProgress { progress in
  161. //self.postProgress(progress: progress)
  162. }.responseData { response in
  163. switch response.result {
  164. case.failure(let error):
  165. completionHandler(error)
  166. case .success( _):
  167. completionHandler(nil)
  168. }
  169. }
  170. }
  171. }