Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Normalize unicode NFC #98

Merged
merged 1 commit into from
Jul 30, 2024
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
2 changes: 1 addition & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
@@ -1 +1 @@
.DS_Store
**/.DS_Store
2 changes: 1 addition & 1 deletion Sources/SMBClient/FileWriter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public class FileWriter {

init(session: Session, path: String) {
self.session = session
self.path = path
self.path = path.precomposedStringWithCanonicalMapping
}

public func upload(data: Data) async throws {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ extension NTStatus: CustomStringConvertible {
return "The network name specified by the client has been deleted on the server. This error is returned if the client specifies an incorrect TID or the share on the server represented by the TID was deleted."
case .badNetworkName:
return "The specified share name cannot be found on the remote server."
case .directoryNotEmpty:
return "Indicates that the directory trying to be deleted is not empty."
case .notADirectory:
return "A requested opened file is not a directory."
case .fileClosed:
Expand All @@ -87,6 +89,8 @@ extension NTStatus: CustomStringConvertible {
return "The transport-connection attempt was refused by the remote system."
case .networkSessionExpired:
return "The client's session has expired; therefore, the client MUST re-authenticate to continue accessing remote resources."
case .fileSystemLimitation:
return "The requested operation could not be completed due to a file system limitation."
case .smbTooManyUIDs:
return "The client has requested too many UID values from the server or the client already has an SMB session setup with this UID value."
default:
Expand Down Expand Up @@ -164,6 +168,8 @@ extension NTStatus: CustomDebugStringConvertible {
return "NETWORK_NAME_DELETED"
case .badNetworkName:
return "BAD_NETWORK_NAME"
case .directoryNotEmpty:
return "DIRECTORY_NOT_EMPTY"
case .notADirectory:
return "NOT_A_DIRECTORY"
case .fileClosed:
Expand All @@ -174,6 +180,8 @@ extension NTStatus: CustomDebugStringConvertible {
return "CONNECTION_REFUSED"
case .networkSessionExpired:
return "NETWORK_SESSION_EXPIRED"
case .fileSystemLimitation:
return "FILE_SYSTEM_LIMITATION"
case .smbTooManyUIDs:
return "SMB_TOO_MANY_UIDS"
default:
Expand Down Expand Up @@ -216,11 +224,13 @@ public enum ErrorCode: UInt32 {
case notSupported = 0xC00000BB
case networkNameDeleted = 0xC00000C9
case badNetworkName = 0xC00000CC
case directoryNotEmpty = 0xC0000101
case notADirectory = 0xC0000103
case fileClosed = 0xC0000128
case userSessionDeleted = 0xC0000203
case connectionRefused = 0xC0000236
case networkSessionExpired = 0xC000035C
case fileSystemLimitation = 0xC0000427
case smbTooManyUIDs = 0xC000205A
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ extension Header.Command: CustomDebugStringConvertible {

extension Header.Flags: CustomDebugStringConvertible {
public var debugDescription: String {
var values: [String] = []
var values = [String]()

if contains(.serverToRedir) {
values.append("Response")
Expand Down
4 changes: 2 additions & 2 deletions Sources/SMBClient/SMBClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,15 @@ public class SMBClient {
}

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

public func rename(from: String, to: String) async throws {
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.normalize(from), to: Pathname.normalize(to))
try await session.move(from: Pathname.normalize(from), to: Pathname.normalize(to.precomposedStringWithCanonicalMapping))
}

public func deleteDirectory(path: String) async throws {
Expand Down
50 changes: 3 additions & 47 deletions Sources/SMBClient/Session.swift
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ public class Session {
let response = Logoff.Response(data: data)

sessionId = 0

return response
}

Expand Down Expand Up @@ -461,56 +461,12 @@ public class Session {
shareAccess: [.read, .write, .delete],
createDisposition: .create,
createOptions: [.directoryFile],
name: path
name: path.precomposedStringWithCanonicalMapping
)
try await close(fileId: response.fileId)
return response
}

public func copy(path source: String, path dest: String) async throws {
let createResponse = try await create(
desiredAccess: [.genericRead],
fileAttributes: [],
shareAccess: [.read],
createDisposition: .open,
createOptions: [],
name: source
)

let creditSize = creditSize(size: maxReadSize)
let request = Read.Request(
creditCharge: creditSize,
messageId: messageId.next(count: UInt64(creditSize)),
treeId: treeId,
sessionId: sessionId,
fileId: createResponse.fileId,
offset: 0,
length: maxReadSize
)

var buffer = Data()
var response = Read.Response(data: try await send(request.encoded()))
buffer.append(response.buffer)

while NTStatus(response.header.status) != .endOfFile {
let request = Read.Request(
creditCharge: creditSize,
messageId: messageId.next(count: UInt64(creditSize)),
treeId: treeId,
sessionId: sessionId,
fileId: createResponse.fileId,
offset: UInt64(buffer.count),
length: maxReadSize
)

let data = try await send(request.encoded())
response = Read.Response(data: data)
buffer.append(response.buffer)
}

try await close(fileId: createResponse.fileId)
}

public func deleteDirectory(path: String) async throws {
let files = try await queryDirectory(path: path, pattern: "*")
for file in files {
Expand Down Expand Up @@ -616,7 +572,7 @@ public class Session {
sessionId: sessionId,
fileId: temporaryUUID,
infoType: .file,
fileInformation: FileRenameInformation(fileName: to)
fileInformation: FileRenameInformation(fileName: to.precomposedStringWithCanonicalMapping)
)
let closeRequest = Close.Request(
headerFlags: [.relatedOperations],
Expand Down
Loading