diff --git a/Sources/NextcloudKit/NKCommon.swift b/Sources/NextcloudKit/NKCommon.swift index 6cbd77f5..2b9795a8 100644 --- a/Sources/NextcloudKit/NKCommon.swift +++ b/Sources/NextcloudKit/NKCommon.swift @@ -97,19 +97,26 @@ public class NKCommon: NSObject { internal lazy var sessionConfiguration: URLSessionConfiguration = { let configuration = URLSessionConfiguration.af.default configuration.requestCachePolicy = .reloadIgnoringLocalCacheData + if let groupIdentifier { + let cookieStorage = HTTPCookieStorage.sharedCookieStorage(forGroupContainerIdentifier: groupIdentifier) + configuration.httpCookieStorage = cookieStorage + } else { + configuration.httpCookieStorage = nil + } return configuration }() internal var rootQueue: DispatchQueue = DispatchQueue(label: "com.nextcloud.nextcloudkit.sessionManagerData.rootQueue") internal var requestQueue: DispatchQueue? internal var serializationQueue: DispatchQueue? - internal var internalUser = "" - internal var internalUserId = "" - internal var internalPassword = "" - internal var internalAccount = "" - internal var internalUrlBase = "" - internal var internalUserAgent: String? - internal var internalNextcloudVersion: Int = 0 + internal var _user = "" + internal var _userId = "" + internal var _password = "" + internal var _account = "" + internal var _urlBase = "" + internal var _userAgent: String? + internal var _nextcloudVersion: Int = 0 + internal var _groupIdentifier: String? internal var internalTypeIdentifiers: [UTTypeConformsToServer] = [] internal var utiCache = NSCache() @@ -126,31 +133,35 @@ public class NKCommon: NSObject { private let queueLog = DispatchQueue(label: "com.nextcloud.nextcloudkit.queuelog", attributes: .concurrent ) public var user: String { - return internalUser + return _user } public var userId: String { - return internalUserId + return _userId } public var password: String { - return internalPassword + return _password } public var account: String { - return internalAccount + return _account } public var urlBase: String { - return internalUrlBase + return _urlBase } public var userAgent: String? { - return internalUserAgent + return _userAgent } public var nextcloudVersion: Int { - return internalNextcloudVersion + return _nextcloudVersion + } + + public var groupIdentifier: String? { + return _groupIdentifier } public let backgroundQueue = DispatchQueue(label: "com.nextcloud.nextcloudkit.backgroundqueue", qos: .background, attributes: .concurrent) @@ -225,7 +236,6 @@ public class NKCommon: NSObject { // MARK: - Type Identifier public func getInternalTypeIdentifier(typeIdentifier: String) -> [UTTypeConformsToServer] { - var results: [UTTypeConformsToServer] = [] for internalTypeIdentifier in internalTypeIdentifiers { @@ -233,7 +243,6 @@ public class NKCommon: NSObject { results.append(internalTypeIdentifier) } } - return results } @@ -305,7 +314,6 @@ public class NKCommon: NSObject { iconName = fileProperties.iconName } } - return(mimeType: mimeType, classFile: classFile, iconName: iconName, typeIdentifier: typeIdentifier, fileNameWithoutExt: fileNameWithoutExt, ext: ext) } @@ -367,17 +375,19 @@ public class NKCommon: NSObject { } } } - return fileProperty } // MARK: - Chunked File - public func chunkedFile(inputDirectory: String, outputDirectory: String, fileName: String, chunkSize: Int, filesChunk: [(fileName: String, size: Int64)], + public func chunkedFile(inputDirectory: String, + outputDirectory: String, + fileName: String, + chunkSize: Int, + filesChunk: [(fileName: String, size: Int64)], numChunks: @escaping (_ num: Int) -> Void = { _ in }, counterChunk: @escaping (_ counter: Int) -> Void = { _ in }, completion: @escaping (_ filesChunk: [(fileName: String, size: Int64)]) -> Void = { _ in }) { - // Check if filesChunk is empty if !filesChunk.isEmpty { return completion(filesChunk) } @@ -422,13 +432,10 @@ public class NKCommon: NSObject { } repeat { - if stop { return completion([]) } - if autoreleasepool(invoking: { () -> Int in - if chunk >= chunkSize { writer?.closeFile() writer = nil @@ -461,9 +468,7 @@ public class NKCommon: NSObject { } filesChunk = [] return 0 - }) == 0 { break } - } while true writer?.closeFile() @@ -476,7 +481,6 @@ public class NKCommon: NSObject { filesChunk[counter].size = incrementalSize counter += 1 } - return completion(filesChunk) } @@ -493,15 +497,15 @@ public class NKCommon: NSObject { public func getStandardHeaders(user: String?, password: String?, appendHeaders: [String: String]?, customUserAgent: String?, contentType: String? = nil) -> HTTPHeaders { var headers: HTTPHeaders = [] - if let username = user, let password = password { - headers.update(.authorization(username: username, password: password)) + if let user, let password { + headers.update(.authorization(username: user, password: password)) } - if let customUserAgent = customUserAgent { + if let customUserAgent { headers.update(.userAgent(customUserAgent)) } else if let userAgent = userAgent { headers.update(.userAgent(userAgent)) } - if let contentType = contentType { + if let contentType { headers.update(.contentType(contentType)) } else { headers.update(.contentType("application/x-www-form-urlencoded")) @@ -510,18 +514,16 @@ public class NKCommon: NSObject { headers.update(name: "Accept", value: "application/json") } headers.update(name: "OCS-APIRequest", value: "true") - for (key, value) in appendHeaders ?? [:] { headers.update(name: key, value: value) } - return headers } public func createStandardUrl(serverUrl: String, endpoint: String) -> URLConvertible? { guard var serverUrl = serverUrl.urlEncoded else { return nil } - if serverUrl.last != "/" { serverUrl = serverUrl + "/" } + if serverUrl.last != "/" { serverUrl = serverUrl + "/" } serverUrl = serverUrl + endpoint return serverUrl.asUrl } @@ -532,7 +534,6 @@ public class NKCommon: NSObject { dateFormatter.locale = Locale(identifier: "en_US_POSIX") dateFormatter.dateFormat = format - guard let date = dateFormatter.date(from: dateString) else { return nil } return date } @@ -542,7 +543,6 @@ public class NKCommon: NSObject { dateFormatter.locale = Locale(identifier: "en_US_POSIX") dateFormatter.dateFormat = format - return dateFormatter.string(from: date) } diff --git a/Sources/NextcloudKit/NextcloudKit+API.swift b/Sources/NextcloudKit/NextcloudKit+API.swift index 733f2625..9d61205a 100644 --- a/Sources/NextcloudKit/NextcloudKit+API.swift +++ b/Sources/NextcloudKit/NextcloudKit+API.swift @@ -536,6 +536,25 @@ public extension NextcloudKit { // MARK: - + func getUserProfile(url: String, + user: String, + password: String, + userAgent: String, + taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in }, + completion: @escaping (_ userProfile: NKUserProfile?, _ data: Data?, _ error: NKError) -> Void) { + let endpoint = "ocs/v2.php/cloud/user" + guard let url = self.nkCommonInstance.createStandardUrl(serverUrl: url, endpoint: endpoint) else { + return completion(nil, nil, .urlError) + } + let headers = self.nkCommonInstance.getStandardHeaders(user: user, password: password, appendHeaders: nil, customUserAgent: userAgent) + + getUserProfile(url: url, headers: headers, options: NKRequestOptions()) { task in + taskHandler(task) + } completion: { userProfile, data, error in + completion(userProfile, data, error) + } + } + func getUserProfile(options: NKRequestOptions = NKRequestOptions(), taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in }, completion: @escaping (_ account: String, _ userProfile: NKUserProfile?, _ data: Data?, _ error: NKError) -> Void) { @@ -547,6 +566,18 @@ public extension NextcloudKit { } let headers = self.nkCommonInstance.getStandardHeaders(options: options) + getUserProfile(url: url, headers: headers, options: options) { task in + taskHandler(task) + } completion: { userProfile, data, error in + completion(account, userProfile, data, error) + } + } + + private func getUserProfile(url: URLConvertible, + headers: HTTPHeaders, + options: NKRequestOptions = NKRequestOptions(), + taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in }, + completion: @escaping (_ userProfile: NKUserProfile?, _ data: Data?, _ error: NKError) -> Void) { sessionManager.request(url, method: .get, parameters: nil, encoding: URLEncoding.default, headers: headers, interceptor: nil).validate(statusCode: 200..<300).onURLSessionTaskCreation { task in task.taskDescription = options.taskDescription taskHandler(task) @@ -557,7 +588,7 @@ public extension NextcloudKit { switch response.result { case .failure(let error): let error = NKError(error: error, afResponse: response, responseData: response.data) - options.queue.async { completion(account, nil, nil, error) } + options.queue.async { completion(nil, nil, error) } case .success(let jsonData): let json = JSON(jsonData) let ocs = json["ocs"] @@ -597,9 +628,9 @@ public extension NextcloudKit { userProfile.twitter = data["twitter"].stringValue userProfile.website = data["website"].stringValue - options.queue.async { completion(account, userProfile, jsonData, .success) } + options.queue.async { completion(userProfile, jsonData, .success) } } else { - options.queue.async { completion(account, nil, jsonData, NKError(rootJson: json, fallbackStatusCode: response.response?.statusCode)) } + options.queue.async { completion(nil, jsonData, NKError(rootJson: json, fallbackStatusCode: response.response?.statusCode)) } } } } diff --git a/Sources/NextcloudKit/NextcloudKit+Login.swift b/Sources/NextcloudKit/NextcloudKit+Login.swift index e67c712d..0d3e585a 100644 --- a/Sources/NextcloudKit/NextcloudKit+Login.swift +++ b/Sources/NextcloudKit/NextcloudKit+Login.swift @@ -27,18 +27,18 @@ import SwiftyJSON public extension NextcloudKit { // MARK: - App Password - func getAppPassword(serverUrl: String, - username: String, + func getAppPassword(url: String, + user: String, password: String, userAgent: String? = nil, options: NKRequestOptions = NKRequestOptions(), taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in }, completion: @escaping (_ token: String?, _ data: Data?, _ error: NKError) -> Void) { let endpoint = "ocs/v2.php/core/getapppassword" - guard let url = self.nkCommonInstance.createStandardUrl(serverUrl: serverUrl, endpoint: endpoint) else { + guard let url = self.nkCommonInstance.createStandardUrl(serverUrl: url, endpoint: endpoint) else { return options.queue.async { completion(nil, nil, .urlError) } } - var headers: HTTPHeaders = [.authorization(username: username, password: password)] + var headers: HTTPHeaders = [.authorization(username: user, password: password)] if let userAgent = userAgent { headers.update(.userAgent(userAgent)) } diff --git a/Sources/NextcloudKit/NextcloudKit.swift b/Sources/NextcloudKit/NextcloudKit.swift index cfb7f3a4..9cdc5cfd 100644 --- a/Sources/NextcloudKit/NextcloudKit.swift +++ b/Sources/NextcloudKit/NextcloudKit.swift @@ -71,14 +71,15 @@ open class NextcloudKit: SessionDelegate { // MARK: - Setup - public func setup(account: String? = nil, user: String, userId: String, password: String, urlBase: String, userAgent: String, nextcloudVersion: Int, delegate: NKCommonDelegate?) { - self.setup(account: account, user: user, userId: userId, password: password, urlBase: urlBase) + public func setup(account: String? = nil, user: String, userId: String, password: String, urlBase: String, userAgent: String, nextcloudVersion: Int, groupIdentifier: String? = nil, delegate: NKCommonDelegate?) { + self.setup(account: account, user: user, userId: userId, password: password, urlBase: urlBase, groupIdentifier: groupIdentifier) self.setup(userAgent: userAgent) self.setup(nextcloudVersion: nextcloudVersion) self.setup(delegate: delegate) } - public func setup(account: String? = nil, user: String, userId: String, password: String, urlBase: String) { + public func setup(account: String? = nil, user: String, userId: String, password: String, urlBase: String, groupIdentifier: String? = nil) { + self.nkCommonInstance._groupIdentifier = groupIdentifier if (self.nkCommonInstance.account != account) || (self.nkCommonInstance.urlBase != urlBase && self.nkCommonInstance.user != user) { if let cookieStore = sessionManager.session.configuration.httpCookieStorage { for cookie in cookieStore.cookies ?? [] { @@ -88,15 +89,15 @@ open class NextcloudKit: SessionDelegate { self.nkCommonInstance.internalTypeIdentifiers = [] } - if let account = account { - self.nkCommonInstance.internalAccount = account + if let account { + self.nkCommonInstance._account = account } else { - self.nkCommonInstance.internalAccount = "" + self.nkCommonInstance._account = "" } - self.nkCommonInstance.internalUser = user - self.nkCommonInstance.internalUserId = userId - self.nkCommonInstance.internalPassword = password - self.nkCommonInstance.internalUrlBase = urlBase + self.nkCommonInstance._user = user + self.nkCommonInstance._userId = userId + self.nkCommonInstance._password = password + self.nkCommonInstance._urlBase = urlBase } public func setup(delegate: NKCommonDelegate?) { @@ -104,29 +105,11 @@ open class NextcloudKit: SessionDelegate { } public func setup(userAgent: String) { - self.nkCommonInstance.internalUserAgent = userAgent + self.nkCommonInstance._userAgent = userAgent } public func setup(nextcloudVersion: Int) { - self.nkCommonInstance.internalNextcloudVersion = nextcloudVersion - } - - public func setupSessionManager(sessionConfiguration: URLSessionConfiguration?, - rootQueue: DispatchQueue?, - requestQueue: DispatchQueue?, - serializationQueue: DispatchQueue?) { - if let sessionConfiguration = sessionConfiguration { - self.nkCommonInstance.sessionConfiguration = sessionConfiguration - } - if let rootQueue = rootQueue { - self.nkCommonInstance.rootQueue = rootQueue - } - if let requestQueue = requestQueue { - self.nkCommonInstance.requestQueue = requestQueue - } - if let serializationQueue = serializationQueue { - self.nkCommonInstance.serializationQueue = serializationQueue - } + self.nkCommonInstance._nextcloudVersion = nextcloudVersion } /*