Skip to content

Commit

Permalink
Allow path starts slashes (Absolute path)
Browse files Browse the repository at this point in the history
  • Loading branch information
kishikawakatsumi committed Jul 29, 2024
1 parent c3df189 commit 78a8684
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 19 deletions.
6 changes: 4 additions & 2 deletions Sources/SMBClient/Misc/Pathname.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ enum Pathname {
}
}

static func escape(_ path: String) -> String {
path.replacingOccurrences(of: "/", with: #"\"#)
static func normalize(_ path: String) -> String {
path
.trimmingCharacters(in: CharacterSet(charactersIn: #"/\"#))
.replacingOccurrences(of: "/", with: #"\"#)
}
}
34 changes: 17 additions & 17 deletions Sources/SMBClient/SMBClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,50 +74,50 @@ public class SMBClient {
}

public func listDirectory(path: String, pattern: String = "*") async throws -> [File] {
let files = try await session.queryDirectory(path: Pathname.escape(path), pattern: pattern)
let files = try await session.queryDirectory(path: Pathname.normalize(path), pattern: pattern)
return files.map { File(fileInfo: $0) }
}

public func createDirectory(path: String) async throws {
try await session.createDirectory(path: Pathname.escape(path))
try await session.createDirectory(path: Pathname.normalize(path))
}

public func rename(from: String, to: String) async throws {
try await move(from: Pathname.escape(from), to: Pathname.escape(to))
try await move(from: Pathname.normalize(from), to: Pathname.normalize(to))
}

public func move(from: String, to: String) async throws {
try await session.move(from: Pathname.escape(from), to: Pathname.escape(to))
try await session.move(from: Pathname.normalize(from), to: Pathname.normalize(to))
}

public func deleteDirectory(path: String) async throws {
try await session.deleteDirectory(path: Pathname.escape(path))
try await session.deleteDirectory(path: Pathname.normalize(path))
}

public func deleteFile(path: String) async throws {
try await session.deleteFile(path: Pathname.escape(path))
try await session.deleteFile(path: Pathname.normalize(path))
}

public func fileStat(path: String) async throws -> FileStat {
let response = try await session.fileStat(path: Pathname.escape(path))
let response = try await session.fileStat(path: Pathname.normalize(path))
return FileStat(response)
}

public func existFile(path: String) async throws -> Bool {
try await session.existFile(path: Pathname.escape(path))
try await session.existFile(path: Pathname.normalize(path))
}

public func existDirectory(path: String) async throws -> Bool {
try await session.existDirectory(path: Pathname.escape(path))
try await session.existDirectory(path: Pathname.normalize(path))
}

public func fileInfo(path: String) async throws -> FileAllInformation {
let response = try await session.queryInfo(path: Pathname.escape(path))
let response = try await session.queryInfo(path: Pathname.normalize(path))
return FileAllInformation(data: response.buffer)
}

public func download(path: String) async throws -> Data {
let fileReader = fileReader(path: Pathname.escape(path))
let fileReader = fileReader(path: Pathname.normalize(path))

let data = try await fileReader.download()
try await fileReader.close()
Expand All @@ -126,11 +126,11 @@ public class SMBClient {
}

public func upload(content: Data, path: String) async throws {
try await upload(content: content, path: Pathname.escape(path), progressHandler: { _ in })
try await upload(content: content, path: Pathname.normalize(path), progressHandler: { _ in })
}

public func upload(content: Data, path: String, progressHandler: (_ progress: Double) -> Void) async throws {
let fileWriter = fileWriter(path: Pathname.escape(path))
let fileWriter = fileWriter(path: Pathname.normalize(path))

try await fileWriter.upload(data: content, progressHandler: progressHandler)
try await fileWriter.close()
Expand All @@ -141,7 +141,7 @@ public class SMBClient {
}

public func upload(fileHandle: FileHandle, path: String, progressHandler: (_ progress: Double) -> Void) async throws {
let fileWriter = fileWriter(path: Pathname.escape(path))
let fileWriter = fileWriter(path: Pathname.normalize(path))

try await fileWriter.upload(fileHandle: fileHandle, progressHandler: progressHandler)
try await fileWriter.close()
Expand All @@ -156,18 +156,18 @@ public class SMBClient {
remotePath path: String,
progressHandler: (_ completedFiles: Int, _ fileBeingTransferred: URL, _ bytesSent: Int64) -> Void
) async throws {
let fileWriter = fileWriter(path: Pathname.escape(path))
let fileWriter = fileWriter(path: Pathname.normalize(path))

try await fileWriter.upload(localPath: localPath, progressHandler: progressHandler)
try await fileWriter.close()
}

public func fileReader(path: String) -> FileReader {
FileReader(session: session, path: Pathname.escape(path))
FileReader(session: session, path: Pathname.normalize(path))
}

public func fileWriter(path: String) -> FileWriter {
FileWriter(session: session, path: Pathname.escape(path))
FileWriter(session: session, path: Pathname.normalize(path))
}

public func keepAlive() async throws -> Echo.Response {
Expand Down
86 changes: 86 additions & 0 deletions Tests/SMBClientTests/SMBClientTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,92 @@ final class SMBClientTests: XCTestCase {
try await client.logoff()
}

func testListDirectory06() async throws {
let user = bob
let client = SMBClient(host: "localhost", port: 4445)
try await client.login(username: user.username, password: user.password)

let share = user.share
let shareDirectory = user.sharePath
try await client.connectShare(share)

func listDirectory(share: String, shareDirectory: String, path: String) async throws {
let files = try await client.listDirectory(path: path)
.filter { $0.name != "." && $0.name != ".." }
.sorted { $0.name.localizedStandardCompare($1.name) == .orderedAscending }

let fileManager = FileManager()
let root = fixtureURL.appending(component: "\(shareDirectory)/\(path)")
let testFiles = try fileManager.contentsOfDirectory(atPath: root.path(percentEncoded: false))
.filter { $0 != ".DS_Store" }
.sorted { $0.localizedStandardCompare($1) == .orderedAscending }

for (actualFile, expectedFile) in zip(files, testFiles) {
XCTAssertEqual(actualFile.name, expectedFile)

var isDirectory: ObjCBool = false
fileManager.fileExists(atPath: root.appending(component: expectedFile).path(percentEncoded: false), isDirectory: &isDirectory)
XCTAssertEqual(isDirectory.boolValue, actualFile.isDirectory)

if actualFile.isDirectory {
if path.isEmpty {
try await listDirectory(share: share, shareDirectory: shareDirectory, path: actualFile.name)
} else {
try await listDirectory(share: share, shareDirectory: shareDirectory, path: "\(path)/\(actualFile.name)")
}
}
}
}

try await listDirectory(share: share, shareDirectory: shareDirectory, path: "/test_files")

try await client.treeDisconnect()
try await client.logoff()
}

func testListDirectory07() async throws {
let user = bob
let client = SMBClient(host: "localhost", port: 4445)
try await client.login(username: user.username, password: user.password)

let share = user.share
let shareDirectory = user.sharePath
try await client.connectShare(share)

func listDirectory(share: String, shareDirectory: String, path: String) async throws {
let files = try await client.listDirectory(path: path)
.filter { $0.name != "." && $0.name != ".." }
.sorted { $0.name.localizedStandardCompare($1.name) == .orderedAscending }

let fileManager = FileManager()
let root = fixtureURL.appending(component: "\(shareDirectory)/\(path)")
let testFiles = try fileManager.contentsOfDirectory(atPath: root.path(percentEncoded: false))
.filter { $0 != ".DS_Store" }
.sorted { $0.localizedStandardCompare($1) == .orderedAscending }

for (actualFile, expectedFile) in zip(files, testFiles) {
XCTAssertEqual(actualFile.name, expectedFile)

var isDirectory: ObjCBool = false
fileManager.fileExists(atPath: root.appending(component: expectedFile).path(percentEncoded: false), isDirectory: &isDirectory)
XCTAssertEqual(isDirectory.boolValue, actualFile.isDirectory)

if actualFile.isDirectory {
if path.isEmpty {
try await listDirectory(share: share, shareDirectory: shareDirectory, path: actualFile.name)
} else {
try await listDirectory(share: share, shareDirectory: shareDirectory, path: "\(path)/\(actualFile.name)")
}
}
}
}

try await listDirectory(share: share, shareDirectory: shareDirectory, path: "/")

try await client.treeDisconnect()
try await client.logoff()
}

func testCreateDirectory() async throws {
let user = alice
let client = SMBClient(host: "localhost", port: 4445)
Expand Down

0 comments on commit 78a8684

Please sign in to comment.