From 2fa2ba66d900169fd0fb9473d3f2536a223b9267 Mon Sep 17 00:00:00 2001 From: Marino Faggiana Date: Thu, 29 Jan 2026 09:11:13 +0100 Subject: [PATCH 1/3] added header option Signed-off-by: Marino Faggiana --- Sources/NextcloudKit/NextcloudKit+Upload.swift | 7 +++++++ Sources/NextcloudKit/NextcloudKitBackground.swift | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/Sources/NextcloudKit/NextcloudKit+Upload.swift b/Sources/NextcloudKit/NextcloudKit+Upload.swift index 0aad18e5..a789b880 100644 --- a/Sources/NextcloudKit/NextcloudKit+Upload.swift +++ b/Sources/NextcloudKit/NextcloudKit+Upload.swift @@ -15,6 +15,7 @@ public extension NextcloudKit { /// - dateCreationFile: Optional creation date to include in headers (X-OC-CTime). /// - dateModificationFile: Optional modification date to include in headers (X-OC-MTime). /// - overwrite: If true, the remote file will be overwritten if it already exists. + /// - autoMkcol: When set to 1, instructs the server to automatically create any missing parent directories when uploading a file. /// - account: The account associated with the upload session. /// - options: Optional configuration for the request (headers, queue, timeout, etc.). /// - requestHandler: Called with the created UploadRequest. @@ -33,6 +34,7 @@ public extension NextcloudKit { dateCreationFile: Date? = nil, dateModificationFile: Date? = nil, overwrite: Bool = false, + autoMkcol: Bool = false, account: String, options: NKRequestOptions = NKRequestOptions(), requestHandler: @escaping (_ request: UploadRequest) -> Void = { _ in }, @@ -64,8 +66,13 @@ public extension NextcloudKit { if overwrite { headers.update(name: "Overwrite", value: "true") } + if autoMkcol { + headers.update(name: "X-NC-WebDAV-Auto-Mkcol", value: "1") + } headers.update(.contentType("application/octet-stream")) + // X-NC-WebDAV-Auto-Mkcol + let request = nkSession.sessionData.upload(fileNameLocalPathUrl, to: url, method: .put, headers: headers, interceptor: NKInterceptor(nkCommonInstance: nkCommonInstance), fileManager: .default).validate(statusCode: 200..<300).onURLSessionTaskCreation(perform: { task in task.taskDescription = options.taskDescription options.queue.async { taskHandler(task) } diff --git a/Sources/NextcloudKit/NextcloudKitBackground.swift b/Sources/NextcloudKit/NextcloudKitBackground.swift index 391566f1..7e973b5c 100644 --- a/Sources/NextcloudKit/NextcloudKitBackground.swift +++ b/Sources/NextcloudKit/NextcloudKitBackground.swift @@ -124,6 +124,7 @@ public final class NKBackground: NSObject, URLSessionTaskDelegate, URLSessionDel /// - dateModificationFile: Optional modification date metadata for the file. /// - taskDescription: Optional description to set on the URLSession task. /// - overwrite: Boolean indicating whether to overwrite existing files on the server. + /// - autoMkcol: When set to 1, instructs the server to automatically create any missing parent directories when uploading a file. /// - account: The Nextcloud account associated with the upload. /// - sessionIdentifier: A string identifier for the upload session. /// @@ -136,6 +137,7 @@ public final class NKBackground: NSObject, URLSessionTaskDelegate, URLSessionDel dateModificationFile: Date?, taskDescription: String? = nil, overwrite: Bool = false, + autoMkcol: Bool = false, account: String, automaticResume: Bool = true, sessionIdentifier: String) -> (URLSessionUploadTask?, error: NKError) { @@ -185,6 +187,9 @@ public final class NKBackground: NSObject, URLSessionTaskDelegate, URLSessionDel if overwrite { request.setValue("true", forHTTPHeaderField: "Overwrite") } + if autoMkcol { + request.setValue("1", forHTTPHeaderField: "X-NC-WebDAV-Auto-Mkcol") + } // Epoch of linux do not permitted negativ value if let dateCreationFile, dateCreationFile.timeIntervalSince1970 > 0 { request.setValue("\(dateCreationFile.timeIntervalSince1970)", forHTTPHeaderField: "X-OC-CTime") From 2cba6babd7db4b9c011501e5fd469d792dc3cd25 Mon Sep 17 00:00:00 2001 From: Marino Faggiana Date: Thu, 29 Jan 2026 09:17:08 +0100 Subject: [PATCH 2/3] async parameter Signed-off-by: Marino Faggiana --- Sources/NextcloudKit/NextcloudKit+Upload.swift | 14 +++----------- Sources/NextcloudKit/NextcloudKitBackground.swift | 2 ++ 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/Sources/NextcloudKit/NextcloudKit+Upload.swift b/Sources/NextcloudKit/NextcloudKit+Upload.swift index a789b880..aa20658a 100644 --- a/Sources/NextcloudKit/NextcloudKit+Upload.swift +++ b/Sources/NextcloudKit/NextcloudKit+Upload.swift @@ -111,17 +111,7 @@ public extension NextcloudKit { /// Asynchronously uploads a file to the Nextcloud server. /// - /// - Parameters: - /// - serverUrlFileName: The remote server URL or path where the file will be uploaded. - /// - fileNameLocalPath: The local file path to be uploaded. - /// - dateCreationFile: Optional creation date to include in headers (X-OC-CTime). - /// - dateModificationFile: Optional modification date to include in headers (X-OC-MTime). - /// - overwrite: If true, the remote file will be overwritten if it already exists. - /// - account: The account associated with the upload session. - /// - options: Optional configuration for the request (headers, queue, timeout, etc.). - /// - requestHandler: Called with the created UploadRequest. - /// - taskHandler: Called with the underlying URLSessionTask when it's created. - /// - progressHandler: Called periodically with upload progress. + /// - Parameters: Same as the synchronous version. /// /// - Returns: A tuple containing: /// - account: The account used for the upload. @@ -136,6 +126,7 @@ public extension NextcloudKit { dateCreationFile: Date? = nil, dateModificationFile: Date? = nil, overwrite: Bool = false, + autoMkcol: Bool = false, account: String, options: NKRequestOptions = NKRequestOptions(), requestHandler: @escaping (_ request: UploadRequest) -> Void = { _ in }, @@ -156,6 +147,7 @@ public extension NextcloudKit { dateCreationFile: dateCreationFile, dateModificationFile: dateModificationFile, overwrite: overwrite, + autoMkcol: autoMkcol, account: account, options: options, requestHandler: requestHandler, diff --git a/Sources/NextcloudKit/NextcloudKitBackground.swift b/Sources/NextcloudKit/NextcloudKitBackground.swift index 7e973b5c..85f126e9 100644 --- a/Sources/NextcloudKit/NextcloudKitBackground.swift +++ b/Sources/NextcloudKit/NextcloudKitBackground.swift @@ -230,6 +230,7 @@ public final class NKBackground: NSObject, URLSessionTaskDelegate, URLSessionDel dateModificationFile: Date?, taskDescription: String? = nil, overwrite: Bool = false, + autoMkcol: Bool = false, account: String, automaticResume: Bool = true, sessionIdentifier: String) async -> ( @@ -243,6 +244,7 @@ public final class NKBackground: NSObject, URLSessionTaskDelegate, URLSessionDel dateModificationFile: dateModificationFile, taskDescription: taskDescription, overwrite: overwrite, + autoMkcol: autoMkcol, account: account, automaticResume: automaticResume, sessionIdentifier: sessionIdentifier) From dcb6a332f641d6469c6bf305a7f3845d2486ccf8 Mon Sep 17 00:00:00 2001 From: Marino Faggiana Date: Fri, 30 Jan 2026 09:32:20 +0100 Subject: [PATCH 3/3] lint Signed-off-by: Marino Faggiana --- Sources/NextcloudKit/NextcloudKit+Login.swift | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Sources/NextcloudKit/NextcloudKit+Login.swift b/Sources/NextcloudKit/NextcloudKit+Login.swift index 2cb95d07..a4c0114a 100644 --- a/Sources/NextcloudKit/NextcloudKit+Login.swift +++ b/Sources/NextcloudKit/NextcloudKit+Login.swift @@ -7,7 +7,7 @@ import Alamofire import SwiftyJSON public extension NextcloudKit { - // MARK: - App Password + // MARK: - App Password / Onetime /// Retrieves an app password (token) for the given user credentials and server URL. /// @@ -106,12 +106,12 @@ public extension NextcloudKit { /// - taskHandler: Callback for observing the underlying URLSessionTask. /// - completion: Returns the token string (if any), raw response data, and NKError result. func getAppPasswordOnetime(url: String, - user: String, - onetimeToken: String, - userAgent: String? = nil, - options: NKRequestOptions = NKRequestOptions(), - taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in }, - completion: @escaping (_ token: String?, _ responseData: AFDataResponse?, _ error: NKError) -> Void) { + user: String, + onetimeToken: String, + userAgent: String? = nil, + options: NKRequestOptions = NKRequestOptions(), + taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in }, + completion: @escaping (_ token: String?, _ responseData: AFDataResponse?, _ error: NKError) -> Void) { let endpoint = "ocs/v2.php/core/getapppassword-onetime" guard let url = self.nkCommonInstance.createStandardUrl(serverUrl: url, endpoint: endpoint) else { return options.queue.async { completion(nil, nil, .urlError) }