mirror of
https://github.com/exituser/Pearcleaner.git
synced 2026-09-17 04:58:56 +00:00
v3.5.2
This commit is contained in:
@@ -560,8 +560,8 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
APP_BUILD = 35;
|
||||
APP_VERSION = 3.5.1;
|
||||
APP_BUILD = 36;
|
||||
APP_VERSION = 3.5.2;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
@@ -630,8 +630,8 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
APP_BUILD = 35;
|
||||
APP_VERSION = 3.5.1;
|
||||
APP_BUILD = 36;
|
||||
APP_VERSION = 3.5.2;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
@@ -692,6 +692,8 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
APP_BUILD = 36;
|
||||
APP_VERSION = 3.5.2;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_ENTITLEMENTS = Pearcleaner/Resources/Pearcleaner.entitlements;
|
||||
@@ -728,6 +730,8 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
APP_BUILD = 36;
|
||||
APP_VERSION = 3.5.2;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_ENTITLEMENTS = Pearcleaner/Resources/Pearcleaner.entitlements;
|
||||
|
||||
@@ -46,11 +46,10 @@ class AppInfoFetcher {
|
||||
return nil
|
||||
}
|
||||
|
||||
// let appName = bundle.localizedInfoDictionary?[kCFBundleNameKey as String] as? String
|
||||
// ?? bundle.infoDictionary?["CFBundleName"] as? String
|
||||
// ?? path.deletingPathExtension().lastPathComponent
|
||||
// let appName = bundle.infoDictionary?["CFBundleDisplayName"] as? String ?? bundle.infoDictionary?["CFBundleName"] as? String
|
||||
// ?? bundle.localizedInfoDictionary?[kCFBundleNameKey as String] as? String ?? path.deletingPathExtension().lastPathComponent
|
||||
|
||||
let appName = path.deletingPathExtension().lastPathComponent.capitalizingFirstLetter()
|
||||
let appName = wrapped ? path.deletingLastPathComponent().deletingLastPathComponent().deletingPathExtension().lastPathComponent.capitalizingFirstLetter() : path.deletingPathExtension().lastPathComponent.capitalizingFirstLetter()
|
||||
|
||||
let appVersion = bundle.infoDictionary?["CFBundleShortVersionString"] as? String
|
||||
?? bundle.infoDictionary?["CFBundleVersion"] as? String
|
||||
@@ -76,101 +75,3 @@ class AppInfoFetcher {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// OLD FUNCTION ============================================================
|
||||
|
||||
//func getAppInfo(atPath path: URL, wrapped: Bool = false) -> AppInfo? {
|
||||
// let filemanager = FileManager.default
|
||||
// let wrapperURL = path.appendingPathComponent("Wrapper")
|
||||
// if filemanager.fileExists(atPath: wrapperURL.path) {
|
||||
// do {
|
||||
// let contents = try filemanager.contentsOfDirectory(at: wrapperURL, includingPropertiesForKeys: nil, options: [])
|
||||
// let appFiles = contents.filter { $0.pathExtension == "app" }
|
||||
//
|
||||
// if let firstAppFile = appFiles.first {
|
||||
// let fullPath = wrapperURL.appendingPathComponent(firstAppFile.lastPathComponent)
|
||||
// if let wrappedAppInfo = getAppInfo(atPath: fullPath, wrapped: true) {
|
||||
// return wrappedAppInfo
|
||||
// }
|
||||
// } else {
|
||||
// printOS("No .app files found in the 'Wrapper' directory: \(wrapperURL)")
|
||||
// }
|
||||
// } catch {
|
||||
// printOS("Error reading contents of 'Wrapper' directory: \(error.localizedDescription)\n\(wrapperURL)")
|
||||
// }
|
||||
// } else {
|
||||
// if let bundle = Bundle(url: path) {
|
||||
// if let bundleIdentifier = bundle.bundleIdentifier {
|
||||
// var appVersion: String?
|
||||
// var appIcon: NSImage?
|
||||
// var appName: String?
|
||||
// var webApp: Bool?
|
||||
// var wrappedApp: Bool?
|
||||
// var system: Bool?
|
||||
//
|
||||
// if let shortVersion = bundle.infoDictionary?["CFBundleShortVersionString"] as? String, !shortVersion.isEmpty {
|
||||
// appVersion = shortVersion
|
||||
// } else {
|
||||
// if let bundleVersion = bundle.infoDictionary?["CFBundleVersion"] as? String, !bundleVersion.isEmpty {
|
||||
// appVersion = bundleVersion
|
||||
// } else {
|
||||
// printOS("Failed to retrieve bundle version")
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if let localizedName = bundle.localizedInfoDictionary?[kCFBundleNameKey as String] as? String {
|
||||
// appName = localizedName
|
||||
// } else if let bundleName = bundle.infoDictionary?["CFBundleName"] as? String {
|
||||
// appName = bundleName
|
||||
// } else {
|
||||
// appName = path.deletingPathExtension().lastPathComponent
|
||||
// }
|
||||
//
|
||||
// // Get icon from app
|
||||
// if path.absoluteString.contains("Wrapper") {
|
||||
// appIcon = getIconForFileOrFolderNS(atPath: path.deletingLastPathComponent().deletingLastPathComponent())
|
||||
// } else {
|
||||
// appIcon = getIconForFileOrFolderNS(atPath: path)
|
||||
// }
|
||||
//
|
||||
// // Convert the icon to a 100x100 PNG image
|
||||
// if let pngIcon = appIcon.flatMap({ convertICNSToPNG(icon: $0, size: NSSize(width: 100, height: 100)) }) {
|
||||
// appIcon = pngIcon
|
||||
// }
|
||||
//
|
||||
// if appIcon == nil {
|
||||
// printOS("App Icon not found for app at path: \(path)")
|
||||
// }
|
||||
//
|
||||
// if bundle.infoDictionary?["LSTemplateApplication"] is Bool {
|
||||
// webApp = true
|
||||
// } else {
|
||||
// webApp = false
|
||||
// }
|
||||
//
|
||||
// if wrapped {
|
||||
// wrappedApp = true
|
||||
// } else {
|
||||
// wrappedApp = false
|
||||
// }
|
||||
//
|
||||
// if !path.path.contains(home) {
|
||||
// system = true
|
||||
// } else {
|
||||
// system = false
|
||||
// }
|
||||
//
|
||||
//
|
||||
// return AppInfo(id: UUID(), path: path, bundleIdentifier: bundleIdentifier, appName: appName ?? "", appVersion: appVersion ?? "", appIcon: appIcon, webApp: webApp ?? false, wrapped: wrappedApp ?? false, system: system ?? false, files: [], fileSize: [:], fileIcon: [:])
|
||||
//
|
||||
// } else {
|
||||
// printOS("Bundle identifier not found at path: \(path)")
|
||||
// }
|
||||
// } else {
|
||||
// printOS("Bundle not found at path: \(path)")
|
||||
// }
|
||||
// }
|
||||
// return nil
|
||||
//}
|
||||
|
||||
@@ -176,34 +176,70 @@ class AppPathFinder {
|
||||
}
|
||||
|
||||
|
||||
private func getGroupContainers(bundleURL: URL) -> [URL] {
|
||||
// Get group containers
|
||||
var staticCode: SecStaticCode?
|
||||
private func getAllContainers(bundleURL: URL) -> [URL] {
|
||||
var containers = [URL]()
|
||||
|
||||
guard SecStaticCodeCreateWithPath(bundleURL as CFURL, [], &staticCode) == errSecSuccess else {
|
||||
return []
|
||||
// Extract bundle identifier from bundleURL
|
||||
let bundleIdentifier = Bundle(url: bundleURL)?.bundleIdentifier
|
||||
|
||||
// Ensure the bundleIdentifier is not nil
|
||||
guard let containerBundleIdentifier = bundleIdentifier else {
|
||||
printOS("Get Containers: No bundle identifier found for the given bundle URL.")
|
||||
return containers // Returns whatever was found so far, possibly empty
|
||||
}
|
||||
|
||||
var signingInformation: CFDictionary?
|
||||
|
||||
let status = SecCodeCopySigningInformation(staticCode!, SecCSFlags(), &signingInformation)
|
||||
|
||||
if status != errSecSuccess {
|
||||
printOS("Failed to copy signing information. Status: \(status)")
|
||||
return []
|
||||
// Get the regular container URL for the extracted bundle identifier
|
||||
if let groupContainer = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: containerBundleIdentifier) {
|
||||
containers.append(groupContainer)
|
||||
} else {
|
||||
printOS("Get Containers: Failed to retrieve container URL for bundle identifier: \(containerBundleIdentifier)")
|
||||
}
|
||||
|
||||
guard let topDict = signingInformation as? [String: Any],
|
||||
let entitlementsDict = topDict["entitlements-dict"] as? [String: Any],
|
||||
let appGroups = entitlementsDict["com.apple.security.application-groups"] as? [String] else {
|
||||
// printOS("No application groups to extract from entitlements for this app.")
|
||||
return []
|
||||
let containersPath = FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask).first?.appendingPathComponent("Containers")
|
||||
|
||||
do {
|
||||
let containerDirectories = try FileManager.default.contentsOfDirectory(at: containersPath!, includingPropertiesForKeys: nil, options: .skipsHiddenFiles)
|
||||
|
||||
// Define a regular expression to match UUID format
|
||||
let uuidRegex = try NSRegularExpression(pattern: "^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$", options: .caseInsensitive)
|
||||
|
||||
for directory in containerDirectories {
|
||||
let directoryName = directory.lastPathComponent
|
||||
|
||||
// Check if the directory name matches the UUID pattern
|
||||
if uuidRegex.firstMatch(in: directoryName, options: [], range: NSRange(location: 0, length: directoryName.utf16.count)) != nil {
|
||||
// Attempt to read the metadata plist file
|
||||
let metadataPlistURL = directory.appendingPathComponent(".com.apple.containermanagerd.metadata.plist")
|
||||
if let metadataDict = NSDictionary(contentsOf: metadataPlistURL), let applicationBundleID = metadataDict["MCMMetadataIdentifier"] as? String {
|
||||
if applicationBundleID == self.appInfo.bundleIdentifier {
|
||||
containers.append(directory)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
printOS("Error accessing the Containers directory: \(error)")
|
||||
}
|
||||
|
||||
let groupContainersPath = appGroups.map { URL(fileURLWithPath: "\(home)/Library/Group Containers/" + $0) }
|
||||
let existingGroupContainers = groupContainersPath.filter { FileManager.default.fileExists(atPath: $0.path) }
|
||||
|
||||
return existingGroupContainers
|
||||
// let fileURL = URL(fileURLWithPath: "/Users/alin/Library/Containers/2792352D-95FE-43AE-947D-FF4BF31DE4E6")
|
||||
//
|
||||
// do {
|
||||
// // Retrieve the localized name
|
||||
// let resourceValues = try fileURL.resourceValues(forKeys: [.localizedNameKey])
|
||||
// if let localizedName = resourceValues.localizedName {
|
||||
// print("Localized Name: \(localizedName)")
|
||||
// } else {
|
||||
// print("Localized name not available.")
|
||||
// }
|
||||
// } catch {
|
||||
// print("Error retrieving localized name: \(error)")
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// Return all found containers
|
||||
return containers
|
||||
}
|
||||
|
||||
|
||||
@@ -231,13 +267,13 @@ class AppPathFinder {
|
||||
|
||||
private func finalizeCollection() {
|
||||
DispatchQueue.global(qos: .userInitiated).async {
|
||||
// let groupContainers = self.getGroupContainers(bundleURL: self.appInfo.path)
|
||||
let allContainers = self.getAllContainers(bundleURL: self.appInfo.path)
|
||||
let outliers = self.handleOutliers()
|
||||
var tempCollection: [URL] = []
|
||||
self.collectionAccessQueue.sync {
|
||||
tempCollection = self.collection
|
||||
}
|
||||
// tempCollection.append(contentsOf: groupContainers)
|
||||
tempCollection.append(contentsOf: allContainers)
|
||||
tempCollection.append(contentsOf: outliers)
|
||||
|
||||
// Sort and standardize URLs to ensure consistent comparisons
|
||||
|
||||
Reference in New Issue
Block a user