mirror of
https://github.com/keymanapp/keyman.git
synced 2026-09-26 01:27:42 +00:00
feat(mac): ensure that home directory is not written to logs
also replace references to URL.path with URL.path(percentEncoded: false) because FileManager operation do not expect percent encoding
This commit is contained in:
parent
af6806666a
commit
7d622997cb
8 changed files with 78 additions and 54 deletions
|
|
@ -58,15 +58,15 @@ public class DownloadCoordinator: NSObject, ObservableObject, WKNavigationDelega
|
|||
// get the package id (though it appears to be identifying a keyboard in the URL)
|
||||
let matchPackageId = String(match.4)
|
||||
if let downloadUrl = self.settings?.buildDownloadPackageUrl(for: matchPackageId) {
|
||||
Logger.download.info("package install, download url = \(downloadUrl.absoluteString, privacy: .public)")
|
||||
LogUtil.infoBreadcrumb("package install, download url = \(downloadUrl.absoluteString)", category: .download)
|
||||
Logger.download.info("package install, download url = \(downloadUrl.cleanUrlPath(), privacy: .public)")
|
||||
LogUtil.infoBreadcrumb("package install, download url = \(downloadUrl.cleanUrlPath())", category: .download)
|
||||
|
||||
let newRequest = URLRequest(url: downloadUrl)
|
||||
|
||||
DispatchQueue.main.async {
|
||||
webView.startDownload(using: newRequest) { download in
|
||||
Logger.download.info("download initiated to \(newRequest.url?.absoluteString ?? "nil", privacy: .public)")
|
||||
LogUtil.infoBreadcrumb("download initiated to \(newRequest.url?.absoluteString ?? "nil")", category: .download)
|
||||
Logger.download.info("download initiated to \(newRequest.url?.cleanUrlPath() ?? "nil", privacy: .public)")
|
||||
LogUtil.infoBreadcrumb("download initiated to \(newRequest.url?.cleanUrlPath() ?? "nil")", category: .download)
|
||||
download.delegate = self
|
||||
self.setupDownloadTracking(download)
|
||||
}
|
||||
|
|
@ -165,8 +165,8 @@ public class DownloadCoordinator: NSObject, ObservableObject, WKNavigationDelega
|
|||
self.progressObserver = nil
|
||||
|
||||
if let downloadDestination = installHelper?.temporaryKmpFileLocation {
|
||||
Logger.download.info("download of \(downloadDestination.path, privacy: .public) was successful.")
|
||||
LogUtil.infoBreadcrumb("download of \(downloadDestination.path) was successful.", category: .download)
|
||||
Logger.download.info("download of \(downloadDestination.cleanUrlPath(), privacy: .public) was successful.")
|
||||
LogUtil.infoBreadcrumb("download of \(downloadDestination.cleanUrlPath()) was successful.", category: .download)
|
||||
|
||||
if let settings {
|
||||
do {
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ public class InputMethodUtil {
|
|||
return false
|
||||
}
|
||||
|
||||
return FileManager.default.fileExists(atPath: inputMethodUrl.path)
|
||||
return FileManager.default.fileExists(atPath: inputMethodUrl.path(percentEncoded: false))
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -214,8 +214,8 @@ public class InputMethodUtil {
|
|||
let process = Process()
|
||||
if let executableUrl = self.pathUtil.buildInputMethodExecutableUrl(fileName: self.keymanInputMethodApplicationName) {
|
||||
process.executableURL = executableUrl
|
||||
Logger.setup.info("invoking Keyman at: \(String(describing: process.executableURL), privacy: .public)")
|
||||
LogUtil.infoBreadcrumb("invoking Keyman at: \(String(describing: process.executableURL))", category: .setup)
|
||||
Logger.setup.info("invoking Keyman at: \(String(describing: process.executableURL?.cleanUrlPath()), privacy: .public)")
|
||||
LogUtil.infoBreadcrumb("invoking Keyman at: \(String(describing: process.executableURL?.cleanUrlPath()))", category: .setup)
|
||||
process.arguments = [argument]
|
||||
}
|
||||
|
||||
|
|
@ -253,8 +253,8 @@ public class InputMethodUtil {
|
|||
|
||||
NSWorkspace.shared.openApplication(at: inputMethodUrl, configuration: openConfig) { (app, error) in
|
||||
if let error = error {
|
||||
Logger.setup.error("Could not launch Keyman input method at \(inputMethodUrl), due to error: \(error as NSError, privacy: .public)")
|
||||
LogUtil.errorBreadcrumb("Could not launch Keyman input method at \(inputMethodUrl), due to error: \(error as NSError)", category: .setup)
|
||||
Logger.setup.error("Could not launch Keyman input method at \(inputMethodUrl.cleanUrlPath()), due to error: \(error as NSError, privacy: .public)")
|
||||
LogUtil.errorBreadcrumb("Could not launch Keyman input method at \(inputMethodUrl.cleanUrlPath()), due to error: \(error as NSError)", category: .setup)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,31 @@
|
|||
|
||||
import Sentry
|
||||
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
* Extend URL to add function that cleans path strings, removing the home directory from the path.
|
||||
*/
|
||||
extension URL {
|
||||
/**
|
||||
* If the path contains the user's home, replace it with ~ as the home directory name
|
||||
* may contain the user's name and should not be written to the logs.
|
||||
*/
|
||||
public func cleanUrlPath() -> String {
|
||||
guard self.isFileURL else { return self.absoluteString }
|
||||
|
||||
let unescapedPath = self.path(percentEncoded: false)
|
||||
let homeDirectory = NSHomeDirectory()
|
||||
|
||||
if unescapedPath.hasPrefix(homeDirectory) {
|
||||
let relativeComponent = unescapedPath.dropFirst(homeDirectory.count)
|
||||
return "~\(relativeComponent)"
|
||||
}
|
||||
|
||||
return unescapedPath
|
||||
}
|
||||
}
|
||||
|
||||
public struct LogUtil {
|
||||
public enum LogCategory: String {
|
||||
case setup // related to start of app and installation
|
||||
|
|
|
|||
|
|
@ -153,7 +153,6 @@ public class SettingsContainer : ObservableObject {
|
|||
Logger.data.log("Found documents group container")
|
||||
} catch KeymanPathError.groupContainerNotFound {
|
||||
Logger.data.error("Document group container not found")
|
||||
let message = "Document group container not found."
|
||||
fatalError("Document group container not found.")
|
||||
} catch {
|
||||
Logger.data.error("Unable to access documents in group container, error \(error as NSError, privacy: .public)")
|
||||
|
|
@ -483,8 +482,8 @@ public class SettingsContainer : ObservableObject {
|
|||
* Delegates to the PackageInstallHelper instance to decide whether the package should be installed.
|
||||
*/
|
||||
public func packageDownloadComplete(kmpFileUrl: URL) throws {
|
||||
Logger.setup.info("packageDownloadComplete \(kmpFileUrl, privacy: .public)")
|
||||
LogUtil.infoBreadcrumb("packageDownloadComplete \(kmpFileUrl)", category: .setup)
|
||||
Logger.setup.info("packageDownloadComplete \(kmpFileUrl.cleanUrlPath(), privacy: .public)")
|
||||
LogUtil.infoBreadcrumb("packageDownloadComplete \(kmpFileUrl.cleanUrlPath())", category: .setup)
|
||||
|
||||
do {
|
||||
try self.packageInstall?.prepareToInstall(for: kmpFileUrl)
|
||||
|
|
|
|||
|
|
@ -85,9 +85,9 @@ public class Keyboard: Identifiable, Hashable, Equatable {
|
|||
* validate whether a corresponding kmx file exists for this keyboard
|
||||
*/
|
||||
public func validateKmxFile(in packageDirectory: URL) throws {
|
||||
let kmxFilePath = self.deriveKmxFileUrl(from: packageDirectory).path
|
||||
if !FileManager.default.fileExists(atPath: kmxFilePath) {
|
||||
Logger.data.error("error: could not find kmx file \(kmxFilePath, privacy: .public)")
|
||||
let kmxFilePath = self.deriveKmxFileUrl(from: packageDirectory)
|
||||
if !FileManager.default.fileExists(atPath: kmxFilePath.path(percentEncoded: false)) {
|
||||
Logger.data.error("error: could not find kmx file \(kmxFilePath.cleanUrlPath(), privacy: .public)")
|
||||
throw LoadPackageError.missingKmxFile
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ public struct KeymanPaths {
|
|||
|
||||
// if for some reason it doesn't exist, create it
|
||||
let fileManager = FileManager.default
|
||||
if !fileManager.fileExists(atPath: fontsDirectory.path) {
|
||||
if !fileManager.fileExists(atPath: fontsDirectory.path(percentEncoded: false)) {
|
||||
do {
|
||||
try fileManager.createDirectory(at: fontsDirectory, withIntermediateDirectories: true, attributes: nil)
|
||||
} catch {
|
||||
|
|
@ -113,16 +113,16 @@ public struct KeymanPaths {
|
|||
}
|
||||
|
||||
fileprivate func logPaths() {
|
||||
Logger.setup.debug("documents: \(self.keyman17DocumentsDirectory!.absoluteString)")
|
||||
Logger.setup.debug("keyman 17 packages: \(self.keyman17PackagesDirectory!.absoluteString)")
|
||||
Logger.setup.debug("documents: \(self.keyman17DocumentsDirectory!.cleanUrlPath())")
|
||||
Logger.setup.debug("keyman 17 packages: \(self.keyman17PackagesDirectory!.cleanUrlPath())")
|
||||
|
||||
Logger.setup.debug("support directory: \(self.keyman18SupportDirectory!.absoluteString)")
|
||||
Logger.setup.debug("support keyman directory: \(self.keyman18DataDirectory!.absoluteString)")
|
||||
Logger.setup.debug("keyman 18 packages: \(self.keyman18PackagesDirectory!.absoluteString)")
|
||||
Logger.setup.debug("support directory: \(self.keyman18SupportDirectory!.cleanUrlPath())")
|
||||
Logger.setup.debug("support keyman directory: \(self.keyman18DataDirectory!.cleanUrlPath())")
|
||||
Logger.setup.debug("keyman 18 packages: \(self.keyman18PackagesDirectory!.cleanUrlPath())")
|
||||
|
||||
Logger.setup.debug("container: \(self.keyman19ContainerDirectory.absoluteString)")
|
||||
Logger.setup.debug("preferences: \(self.keyman19PreferencesDirectory.absoluteString)")
|
||||
Logger.setup.debug("keyman 19 packages: \(self.keyman19PackagesDirectory.absoluteString)")
|
||||
Logger.setup.debug("container: \(self.keyman19ContainerDirectory.cleanUrlPath())")
|
||||
Logger.setup.debug("preferences: \(self.keyman19PreferencesDirectory.cleanUrlPath())")
|
||||
Logger.setup.debug("keyman 19 packages: \(self.keyman19PackagesDirectory.cleanUrlPath())")
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ public class PackageInstallHelper: Identifiable {
|
|||
* Indicates that a package has been downloaded and can be prepared for installation
|
||||
*/
|
||||
public func packageDownloadComplete(for kmpFileUrl: URL) throws {
|
||||
Logger.data.log("packageDownloadComplete \(kmpFileUrl.path, privacy: .public)")
|
||||
Logger.data.log("packageDownloadComplete \(kmpFileUrl.cleanUrlPath(), privacy: .public)")
|
||||
|
||||
try self.prepareToInstall(for: kmpFileUrl)
|
||||
}
|
||||
|
|
@ -80,7 +80,7 @@ public class PackageInstallHelper: Identifiable {
|
|||
*
|
||||
*/
|
||||
public func prepareToInstall(for kmpFileUrl: URL) throws {
|
||||
Logger.data.log("prepareToInstall \(kmpFileUrl.path, privacy: .public)")
|
||||
Logger.data.log("prepareToInstall \(kmpFileUrl.cleanUrlPath(), privacy: .public)")
|
||||
|
||||
do {
|
||||
// unzip to the temp directory
|
||||
|
|
@ -104,8 +104,8 @@ public class PackageInstallHelper: Identifiable {
|
|||
self.packageInstallationType = self.determinePackageInstallationType(newPackage: package)
|
||||
} catch {
|
||||
self.cleanupFailedInstallation()
|
||||
Logger.data.error("package installation failed for \(kmpFileUrl) with error: \(error as NSError, privacy: .public)")
|
||||
LogUtil.errorBreadcrumb("package installation failed for \(kmpFileUrl) with error: \(error as NSError)", category: .data)
|
||||
Logger.data.error("package installation failed for \(kmpFileUrl.cleanUrlPath(), privacy: .public) with error: \(error as NSError, privacy: .public)")
|
||||
LogUtil.errorBreadcrumb("package installation failed for \(kmpFileUrl.cleanUrlPath()) with error: \(error as NSError)", category: .data)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
|
@ -185,7 +185,7 @@ public class PackageInstallHelper: Identifiable {
|
|||
includingPropertiesForKeys: [.isDirectoryKey],
|
||||
options: [.skipsHiddenFiles]) }
|
||||
catch {
|
||||
Logger.data.error("error: unable to get contents of package fonts directory at \(installLocation.path, privacy: .public) with error: \(error as NSError, privacy: .public)")
|
||||
Logger.data.error("error: unable to get contents of package fonts directory at \(installLocation.cleanUrlPath(), privacy: .public) with error: \(error as NSError, privacy: .public)")
|
||||
}
|
||||
|
||||
for fontUrl in fileUrls {
|
||||
|
|
@ -228,7 +228,7 @@ public class PackageInstallHelper: Identifiable {
|
|||
let fileManager = FileManager.default
|
||||
|
||||
// remove the font from the fonts directory just in case it is an old one
|
||||
if fileManager.fileExists(atPath: fontDestinationUrl.path) {
|
||||
if fileManager.fileExists(atPath: fontDestinationUrl.path(percentEncoded: false)) {
|
||||
Logger.data.info("removed existing font: \(fontDestinationUrl.lastPathComponent, privacy: .public)")
|
||||
LogUtil.infoBreadcrumb("removed existing font: \(fontDestinationUrl.lastPathComponent)", category: .data)
|
||||
try? fileManager.removeItem(at: fontDestinationUrl)
|
||||
|
|
|
|||
|
|
@ -80,8 +80,8 @@ public class PackageRepository: PackageRepo {
|
|||
*
|
||||
*/
|
||||
public func loadSinglePackage(packageUrl: URL) throws -> KeymanPackage {
|
||||
Logger.data.info("loadSinglePackage from url: \(packageUrl, privacy: .public)")
|
||||
LogUtil.infoBreadcrumb("loadSinglePackage from url: \(packageUrl)", category: .data)
|
||||
Logger.data.info("loadSinglePackage from url: \(packageUrl.cleanUrlPath(), privacy: .public)")
|
||||
LogUtil.infoBreadcrumb("loadSinglePackage from url: \(packageUrl.cleanUrlPath())", category: .data)
|
||||
|
||||
guard let source = try readPackageFromDirectory(packageDirectoryUrl: packageUrl) else { throw LoadPackageError.invalidUrl }
|
||||
|
||||
|
|
@ -94,12 +94,12 @@ public class PackageRepository: PackageRepo {
|
|||
* delete the package from disk
|
||||
*/
|
||||
public func deletePackage(package: KeymanPackage) {
|
||||
Logger.data.info("deleting package: \(package.sourceDirectoryUrl, privacy: .public)")
|
||||
LogUtil.infoBreadcrumb("deleting package: \(package.sourceDirectoryUrl)", category: .data)
|
||||
Logger.data.info("deleting package: \(package.sourceDirectoryUrl.cleanUrlPath(), privacy: .public)")
|
||||
LogUtil.infoBreadcrumb("deleting package: \(package.sourceDirectoryUrl.cleanUrlPath())", category: .data)
|
||||
do {
|
||||
try FileManager.default.removeItem(at: package.sourceDirectoryUrl)
|
||||
Logger.data.info("deleted package: \(package.sourceDirectoryUrl, privacy: .public)")
|
||||
LogUtil.infoBreadcrumb("deleted package: \(package.sourceDirectoryUrl)", category: .data)
|
||||
Logger.data.info("deleted package: \(package.sourceDirectoryUrl.cleanUrlPath(), privacy: .public)")
|
||||
LogUtil.infoBreadcrumb("deleted package: \(package.sourceDirectoryUrl.cleanUrlPath())", category: .data)
|
||||
} catch {
|
||||
Logger.data.error("could not delete directory: \(error as NSError, privacy: .public)")
|
||||
LogUtil.errorBreadcrumb("could not delete directory: \(error as NSError)", category: .data)
|
||||
|
|
@ -115,23 +115,23 @@ public class PackageRepository: PackageRepo {
|
|||
let packageTempDirectory = pathUtil.keyman19TempDirectory
|
||||
|
||||
// create the keyman-packages directory if it doesn't already exist
|
||||
if !FileManager.default.fileExists(atPath: packageDirectory.path) {
|
||||
if !FileManager.default.fileExists(atPath: packageDirectory.path(percentEncoded: false)) {
|
||||
try FileManager.default.createDirectory(at: packageDirectory, withIntermediateDirectories: true, attributes: nil)
|
||||
Logger.data.info("Created directory: \(packageDirectory.path, privacy: .public)")
|
||||
LogUtil.infoBreadcrumb("Created directory: \(packageDirectory.path)", category: .data)
|
||||
Logger.data.info("Created directory: \(packageDirectory.cleanUrlPath(), privacy: .public)")
|
||||
LogUtil.infoBreadcrumb("Created directory: \(packageDirectory.cleanUrlPath())", category: .data)
|
||||
} else {
|
||||
Logger.data.info("Directory already exists: \(packageDirectory.path, privacy: .public)")
|
||||
LogUtil.infoBreadcrumb("Directory already exists: \(packageDirectory.path)", category: .data)
|
||||
Logger.data.info("Directory already exists: \(packageDirectory.cleanUrlPath(), privacy: .public)")
|
||||
LogUtil.infoBreadcrumb("Directory already exists: \(packageDirectory.cleanUrlPath())", category: .data)
|
||||
}
|
||||
|
||||
// create the temp directory if it doesn't already exist
|
||||
if !FileManager.default.fileExists(atPath: packageTempDirectory.path) {
|
||||
if !FileManager.default.fileExists(atPath: packageTempDirectory.path(percentEncoded: false)) {
|
||||
try FileManager.default.createDirectory(at: packageTempDirectory, withIntermediateDirectories: true, attributes: nil)
|
||||
Logger.data.info("Created directory: \(packageTempDirectory.path, privacy: .public)")
|
||||
LogUtil.infoBreadcrumb("Created directory: \(packageTempDirectory.path)", category: .data)
|
||||
Logger.data.info("Created directory: \(packageTempDirectory.cleanUrlPath(), privacy: .public)")
|
||||
LogUtil.infoBreadcrumb("Created directory: \(packageTempDirectory.cleanUrlPath())", category: .data)
|
||||
} else {
|
||||
Logger.data.info("Directory already exists: \(packageTempDirectory.path, privacy: .public)")
|
||||
LogUtil.infoBreadcrumb("Directory already exists: \(packageTempDirectory.path)", category: .data)
|
||||
Logger.data.info("Directory already exists: \(packageTempDirectory.cleanUrlPath(), privacy: .public)")
|
||||
LogUtil.infoBreadcrumb("Directory already exists: \(packageTempDirectory.cleanUrlPath())", category: .data)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -208,7 +208,7 @@ public class PackageRepository: PackageRepo {
|
|||
*/
|
||||
func directoryExistsAtPath(directoryUrl: URL) -> Bool {
|
||||
var isDirectory: ObjCBool = false
|
||||
let exists = FileManager.default.fileExists(atPath: directoryUrl.path, isDirectory: &isDirectory)
|
||||
let exists = FileManager.default.fileExists(atPath: directoryUrl.path(percentEncoded: false), isDirectory: &isDirectory)
|
||||
return exists && isDirectory.boolValue
|
||||
}
|
||||
|
||||
|
|
@ -241,8 +241,8 @@ public class PackageRepository: PackageRepo {
|
|||
packageMap[itemUrl] = packageSource
|
||||
}
|
||||
} catch let error as LoadPackageError {
|
||||
Logger.data.error("package at \(itemUrl) could not be loaded: \(error as NSError, privacy: .public)")
|
||||
LogUtil.errorBreadcrumb("package at \(itemUrl) could not be loaded: \(error as NSError)", category: .data)
|
||||
Logger.data.error("package at \(itemUrl.cleanUrlPath(), privacy: .public) could not be loaded: \(error as NSError, privacy: .public)")
|
||||
LogUtil.errorBreadcrumb("package at \(itemUrl.cleanUrlPath()) could not be loaded: \(error as NSError)", category: .data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -260,12 +260,12 @@ public class PackageRepository: PackageRepo {
|
|||
* check the specified directory for the kmp.json file and read it if it exists
|
||||
*/
|
||||
func readPackageFromDirectory(packageDirectoryUrl: URL) throws -> PackageSource? {
|
||||
Logger.data.info("readPackageFromDirectory from url: \(packageDirectoryUrl, privacy: .public)")
|
||||
LogUtil.infoBreadcrumb("readPackageFromDirectory from url: \(packageDirectoryUrl)", category: .data)
|
||||
Logger.data.info("readPackageFromDirectory from url: \(packageDirectoryUrl.cleanUrlPath(), privacy: .public)")
|
||||
LogUtil.infoBreadcrumb("readPackageFromDirectory from url: \(packageDirectoryUrl.cleanUrlPath())", category: .data)
|
||||
var packageSource: PackageSource? = nil
|
||||
let kmpJsonFileUrl = packageDirectoryUrl.appendingPathComponent(packageFileName)
|
||||
|
||||
if !FileManager.default.fileExists(atPath: kmpJsonFileUrl.path) {
|
||||
if !FileManager.default.fileExists(atPath: kmpJsonFileUrl.path(percentEncoded: false)) {
|
||||
throw LoadPackageError.kmpJsonFileNotFound
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue