Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions IONFileTransferLib/Helpers/IONFLTRFileHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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: #"(?<!:)/{2,}(?!/)"#,
with: "/",
options: .regularExpression
)
if (url.absoluteString.contains(":///")) {
// the regex may ommit a slash after ://, which is incorrect because it breaks in case of an absolute file path
urlStringWithoutDuplicateSeparators = urlStringWithoutDuplicateSeparators.replacingOccurrences(of: "://", with: ":///")
}
if let finalUrl = URL(string: urlStringWithoutDuplicateSeparators) {
return finalUrl
}
return url
}
}
2 changes: 1 addition & 1 deletion IONFileTransferLib/Helpers/IONFLTRInputsValidator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class IONFLTRInputsValidator {
///
/// - Parameter url: The file `URL` to check.
/// - Returns: `true` if the URL is a valid file URL, `false` otherwise.
func isFileURLValid(url: URL) -> Bool {
private func isFileURLValid(url: URL) -> Bool {
guard url.isFileURL else { return false }
return true
}
Expand Down
12 changes: 7 additions & 5 deletions IONFileTransferLib/IONFLTRManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand All @@ -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)
}

Expand All @@ -141,7 +143,7 @@ public class IONFLTRManager: NSObject {
request: request,
httpOptions: httpOptions,
uploadOptions: uploadOptions,
fileURL: fileURL,
fileURL: updatedFileURL,
fileHelper: fileHelper
)
}
Expand Down
21 changes: 21 additions & 0 deletions IONFileTransferLibTests/Helpers/IONFLTRFileHelperTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}