diff --git a/IONFileTransferLib/Helpers/IONFLTRFileHelper.swift b/IONFileTransferLib/Helpers/IONFLTRFileHelper.swift index 46e9340..974a9c8 100644 --- a/IONFileTransferLib/Helpers/IONFLTRFileHelper.swift +++ b/IONFileTransferLib/Helpers/IONFLTRFileHelper.swift @@ -39,4 +39,26 @@ class IONFLTRFileHelper { func mimeType(for url: URL) -> String? { return UTType(filenameExtension: url.pathExtension)?.preferredMIMEType } + + /// Remove duplicate slahes (file separator '/') from local file URLs + /// + /// The only exception being the slashes indicating the scheme (e.g. 'file://') + /// + /// - Parameter url: The file URL. + /// - Returns: The file URL with duplicate slashes removed + func removeDuplicateSlashes(for url: URL) -> URL { + var urlStringWithoutDuplicateSeparators = url.absoluteString.replacingOccurrences( + of: #"(? Bool { + private func isFileURLValid(url: URL) -> Bool { guard url.isFileURL else { return false } return true } diff --git a/IONFileTransferLib/IONFLTRManager.swift b/IONFileTransferLib/IONFLTRManager.swift index 79511f3..8eb565c 100644 --- a/IONFileTransferLib/IONFLTRManager.swift +++ b/IONFileTransferLib/IONFLTRManager.swift @@ -110,8 +110,9 @@ public class IONFLTRManager: NSObject { /// - Returns: A configured `URLRequest` for the download operation. /// - Throws: An error if validation or directory creation fails. private func prepareForDownload(serverURL: URL, fileURL: URL, httpOptions: IONFLTRHttpOptions) throws -> URLRequest { - try inputsValidator.validateTransferInputs(serverURL: serverURL, fileURL: fileURL) - try fileHelper.createParentDirectories(for: fileURL) + let updatedFileURL = fileHelper.removeDuplicateSlashes(for: fileURL) + try inputsValidator.validateTransferInputs(serverURL: serverURL, fileURL: updatedFileURL) + try fileHelper.createParentDirectories(for: updatedFileURL) return try urlRequestHelper.setupRequest(serverURL: serverURL, httpOptions: httpOptions) } @@ -130,9 +131,10 @@ public class IONFLTRManager: NSObject { uploadOptions: IONFLTRUploadOptions, httpOptions: IONFLTRHttpOptions ) throws -> (URLRequest, URL) { - try inputsValidator.validateTransferInputs(serverURL: serverURL, fileURL: fileURL) + let updatedFileURL = fileHelper.removeDuplicateSlashes(for: fileURL) + try inputsValidator.validateTransferInputs(serverURL: serverURL, fileURL: updatedFileURL) - guard FileManager.default.fileExists(atPath: fileURL.path) else { + guard FileManager.default.fileExists(atPath: updatedFileURL.path) else { throw IONFLTRException.fileDoesNotExist(cause: nil) } @@ -141,7 +143,7 @@ public class IONFLTRManager: NSObject { request: request, httpOptions: httpOptions, uploadOptions: uploadOptions, - fileURL: fileURL, + fileURL: updatedFileURL, fileHelper: fileHelper ) } diff --git a/IONFileTransferLibTests/Helpers/IONFLTRFileHelperTests.swift b/IONFileTransferLibTests/Helpers/IONFLTRFileHelperTests.swift index 5cd5aa8..acac4eb 100644 --- a/IONFileTransferLibTests/Helpers/IONFLTRFileHelperTests.swift +++ b/IONFileTransferLibTests/Helpers/IONFLTRFileHelperTests.swift @@ -53,4 +53,25 @@ final class IONFLTRFileHelperTests: XCTestCase { XCTAssertNil(fileHelper.mimeType(for: unknownURL)) } + + func testRemoveDuplicateSlashes_withoutDuplicates() { + let inputURL = URL(fileURLWithPath:"/path/to/file") + let expectedURL = URL(fileURLWithPath:"/path/to/file") + + XCTAssertEqual(fileHelper.removeDuplicateSlashes(for: inputURL), expectedURL) + } + + func testRemoveDuplicateSlashes_withDuplicatesInEnd() { + let inputURL = URL(fileURLWithPath:"/path/to/file//") + let expectedURL = URL(fileURLWithPath:"/path/to/file/") + + XCTAssertEqual(fileHelper.removeDuplicateSlashes(for: inputURL), expectedURL) + } + + func testRemoveDuplicateSlashes_withDuplicatesInSeveralPlaces() { + let inputURL = URL(fileURLWithPath:"//path///to/file//") + let expectedURL = URL(fileURLWithPath:"/path/to/file/") + + XCTAssertEqual(fileHelper.removeDuplicateSlashes(for: inputURL), expectedURL) + } }