69 lines
2.5 KiB
Swift
69 lines
2.5 KiB
Swift
// SPDX-FileCopyrightText: 2026 Kaede Akino
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
import Foundation
|
|
|
|
public nonisolated struct SoftwareKeyFileImportResult: Equatable, Sendable {
|
|
public var privateKey: String?
|
|
public var certificate: String?
|
|
public var inferredName: String?
|
|
public init(privateKey: String? = nil, certificate: String? = nil, inferredName: String? = nil) {
|
|
self.privateKey = privateKey
|
|
self.certificate = certificate
|
|
self.inferredName = inferredName
|
|
}
|
|
}
|
|
|
|
public nonisolated enum SoftwareKeyFileImporter {
|
|
public static func shouldInferName(from currentName: String) -> Bool {
|
|
currentName.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
|
|
}
|
|
|
|
public static func read(
|
|
urls: [URL], infersName: Bool
|
|
) throws -> SoftwareKeyFileImportResult {
|
|
guard !urls.isEmpty else { return SoftwareKeyFileImportResult() }
|
|
var result = SoftwareKeyFileImportResult()
|
|
for url in urls {
|
|
let text = try readText(at: url)
|
|
if text.contains("PRIVATE KEY") {
|
|
result.privateKey = text
|
|
if infersName { result.inferredName = url.lastPathComponent }
|
|
} else if text.contains("-cert-v01@openssh.com") {
|
|
result.certificate = text.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
} else {
|
|
throw CocoaError(
|
|
.fileReadCorruptFile,
|
|
userInfo: [
|
|
NSLocalizedDescriptionKey: String(
|
|
localized: "Choose a private key or OpenSSH user certificate file."
|
|
)
|
|
]
|
|
)
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
public static func unexpectedFileError() -> CocoaError {
|
|
CocoaError(
|
|
.fileReadCorruptFile,
|
|
userInfo: [
|
|
NSLocalizedDescriptionKey: String(
|
|
localized: "Choose a private key or OpenSSH user certificate file."
|
|
)
|
|
]
|
|
)
|
|
}
|
|
|
|
private static func readText(at url: URL) throws -> String {
|
|
let scoped = url.startAccessingSecurityScopedResource()
|
|
defer { if scoped { url.stopAccessingSecurityScopedResource() } }
|
|
let values = try url.resourceValues(forKeys: [.fileSizeKey, .isRegularFileKey])
|
|
guard values.isRegularFile == true, (values.fileSize ?? 0) <= 8 * 1024 * 1024 else {
|
|
throw CocoaError(.fileReadTooLarge)
|
|
}
|
|
return try String(contentsOf: url, encoding: .utf8)
|
|
}
|
|
}
|