From a465911c5c6fcf1bb04251dae04fc29af49431fa Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Tue, 11 Jun 2024 00:23:25 +0800 Subject: [PATCH] uicache and sbreload updates (#62) * Switch to tbd v4 to support multiple platforms * Update uicache from TrollStore changes * Fix iOS 12 uicache Fix icon name localization Fix detecting whether an app is installed * sbreload: fix entitlements for fallback * man: Update uicache manpages --- .../MobileContainerManager.tbd | 222 +++++++++++------- man/uicache.1 | 12 +- man/zh_CN/uicache.1 | 66 +++--- man/zh_TW/uicache.1 | 29 +-- sbreload.plist | 2 + uicache.m | 140 ++++++----- 6 files changed, 266 insertions(+), 205 deletions(-) diff --git a/Frameworks/MobileContainerManager.framework/MobileContainerManager.tbd b/Frameworks/MobileContainerManager.framework/MobileContainerManager.tbd index c8ce65c..d5ee950 100644 --- a/Frameworks/MobileContainerManager.framework/MobileContainerManager.tbd +++ b/Frameworks/MobileContainerManager.framework/MobileContainerManager.tbd @@ -1,87 +1,139 @@ ---- !tapi-tbd-v3 -archs: [ armv7, armv7s, arm64, arm64e ] -platform: (null) -flags: [ flat_namespace ] -install-name: /System/Library/PrivateFrameworks/MobileContainerManager.framework/MobileContainerManager -current-version: 1 -compatibility-version: 1 -objc-constraint: retain_release +--- !tapi-tbd +tbd-version: 4 +targets: [ x86_64-macos, arm64e-macos, arm64-ios, arm64e-ios, arm64-tvos, arm64e-tvos, armv7-watchos, arm64_32-watchos, arm64e-watchos, arm64-bridgeos ] +install-name: '/System/Library/PrivateFrameworks/MobileContainerManager.framework/MobileContainerManager' exports: - - archs: [ armv7, armv7s, arm64, arm64e ] - symbols: [ _MCMErrorDomain, _MCMFunctionNameErrorKey, - _MCMPathArgumentErrorKey, _MCMSourceFileLineErrorKey, - _kMCMACLFailureError, _kMCMBadInitializerValuesError, - _kMCMBadReplyContentsError, - _kMCMBundleOwnerMigrationFailError, - _kMCMCacheAddError, _kMCMCacheFailedToRebuildError, - _kMCMCacheInconsistencyError, - _kMCMCacheInvalidDataError, _kMCMCacheRemoveError, - _kMCMContainerNotFoundError, - _kMCMContainersWithClassInitError, - _kMCMCreateBaseDirectoryError, - _kMCMCreateContainerClassDirectoryError, - _kMCMCreateDeathRowDirectoryError, - _kMCMCreateReplaceDirectoryError, - _kMCMCreateStagingDirectoryError, - _kMCMCreateSubDirectoryError, - _kMCMCreateTempDirectoryError, - _kMCMDataProtectionFailLockedError, - _kMCMDestroyContainerError, _kMCMExceptionError, - _kMCMExistingContainerReplaceError, - _kMCMFailureToGetErrorReply, - _kMCMGetMetadataErrorError, - _kMCMIdentifierNotFoundInDbError, - _kMCMInvalidCommandError, - _kMCMInvalidContainerObjectError, - _kMCMInvalidEntitlementInfoError, - _kMCMInvalidMetadataError, - _kMCMInvalidMetadataURLMismatchError, - _kMCMInvalidParametersError, _kMCMInvalidReplyError, - _kMCMInvalidURLError, - _kMCMMismatchedClassReplaceError, - _kMCMMismatchedUserReplaceError, - _kMCMMoveStagingToLiveError, - _kMCMMoveToDeathRowError, _kMCMNilIdentifierError, - _kMCMNotEntitledForOperationError, - _kMCMPathNotFoundError, - _kMCMPendingUpdateNoLongerValidError, - _kMCMReadEntitlementFileError, - _kMCMReadMetadataError, _kMCMRegenerateUUIDMoveError, - _kMCMRemoveIndividualStagingDirectoryError, - _kMCMRemoveLegacyDirectoryError, - _kMCMRemoveStagingDirectoryError, - _kMCMRemoveTempContainerError, - _kMCMReplaceContainerError, - _kMCMReplaceMoveToTempError, - _kMCMReplaceRecoverError, _kMCMReplaceRemoveError, - _kMCMReplaceURLError, _kMCMRestoreContainerError, - _kMCMRestorePathExistsError, _kMCMSQLiteError, - _kMCMSQLiteUnexpectedNumChangesError, - _kMCMSameContainerReplaceError, - _kMCMSetSandboxMappingError, _kMCMSetupProxyError, - _kMCMStageForDeleteError, - _kMCMStageSharedContentFailureError, _kMCMSuccess, - _kMCMUndefinedContainerClassError, - _kMCMUnknownSubdirectoriesForClassError, - _kMCMValueNotFoundForKeyError, - _kMCMWriteEntitlementFileError, - _kMCMWriteMetadataDictionaryError, - _kMCMXPCInterruptedReplyError, - _kMCMXPCInvalidReplyError, _kMCMXPCSetupError, - _kMCMXPCUnknownReplyError ] - objc-classes: [ MCMAppContainer, MCMAppDataContainer, MCMContainer, - MCMContainerManager, MCMDataContainer, - MCMFrameworkContainer, - MCMInternalDaemonDataContainer, MCMLazyDescription, - MCMPluginKitPluginContainer, - MCMPluginKitPluginDataContainer, - MCMSharedDataContainer, MCMSharedSystemDataContainer, - MCMSystemDataContainer, MCMTempDirDataContainer, - MCMVPNPluginContainer, MCMVPNPluginDataContainer, - MCMXPCServiceDataContainer ] - objc-ivars: [ MCMContainer._containerClass, - MCMContainer._identifier, - MCMContainer._personaUniqueString, - MCMContainer._thisContainer, MCMContainer._uuid, - MCMLazyDescription._block, MCMLazyDescription._value ] + - targets: [ x86_64-macos, arm64e-macos, arm64-ios, arm64e-ios, arm64-tvos, arm64e-tvos, armv7-watchos, arm64_32-watchos, arm64e-watchos, arm64-bridgeos ] + symbols: [ _MCMErrorDomain, + _MCMFunctionNameErrorKey, + _MCMPathArgumentErrorKey, + _MCMSourceFileLineErrorKey, + _OBJC_CLASS_$_MCMAppContainer, + _OBJC_CLASS_$_MCMAppDataContainer, + _OBJC_CLASS_$_MCMContainer, + _OBJC_CLASS_$_MCMContainerManager, + _OBJC_CLASS_$_MCMDataContainer, + _OBJC_CLASS_$_MCMFrameworkContainer, + _OBJC_CLASS_$_MCMInternalDaemonDataContainer, + _OBJC_CLASS_$_MCMPerUserAppContainer, + _OBJC_CLASS_$_MCMPluginKitPluginContainer, + _OBJC_CLASS_$_MCMPluginKitPluginDataContainer, + _OBJC_CLASS_$_MCMSharedDataContainer, + _OBJC_CLASS_$_MCMSharedSystemDataContainer, + _OBJC_CLASS_$_MCMSystemDataContainer, + _OBJC_CLASS_$_MCMTempDirDataContainer, + _OBJC_CLASS_$_MCMVPNPluginContainer, + _OBJC_CLASS_$_MCMVPNPluginDataContainer, + _OBJC_CLASS_$_MCMXPCServiceDataContainer, + _OBJC_METACLASS_$_MCMAppContainer, + _OBJC_METACLASS_$_MCMAppDataContainer, + _OBJC_METACLASS_$_MCMContainer, + _OBJC_METACLASS_$_MCMContainerManager, + _OBJC_METACLASS_$_MCMDataContainer, + _OBJC_METACLASS_$_MCMFrameworkContainer, + _OBJC_METACLASS_$_MCMInternalDaemonDataContainer, + _OBJC_METACLASS_$_MCMPerUserAppContainer, + _OBJC_METACLASS_$_MCMPluginKitPluginContainer, + _OBJC_METACLASS_$_MCMPluginKitPluginDataContainer, + _OBJC_METACLASS_$_MCMSharedDataContainer, + _OBJC_METACLASS_$_MCMSharedSystemDataContainer, + _OBJC_METACLASS_$_MCMSystemDataContainer, + _OBJC_METACLASS_$_MCMTempDirDataContainer, + _OBJC_METACLASS_$_MCMVPNPluginContainer, + _OBJC_METACLASS_$_MCMVPNPluginDataContainer, + _OBJC_METACLASS_$_MCMXPCServiceDataContainer, + _kMCMACLFailureError, + _kMCMBadInitializerValuesError, + _kMCMBadReplyContentsError, + _kMCMBundleOwnerMigrationFailError, + _kMCMCacheAddError, + _kMCMCacheFailedToRebuildError, + _kMCMCacheInconsistencyError, + _kMCMCacheInvalidDataError, + _kMCMCacheRemoveError, + _kMCMContainerNotFoundError, + _kMCMContainersWithClassInitError, + _kMCMCreateBaseDirectoryError, + _kMCMCreateContainerClassDirectoryError, + _kMCMCreateDeathRowDirectoryError, + _kMCMCreateReplaceDirectoryError, + _kMCMCreateStagingDirectoryError, + _kMCMCreateSubDirectoryError, + _kMCMCreateTempDirectoryError, + _kMCMDataProtectionFailLockedError, + _kMCMDestroyContainerError, + _kMCMExceptionError, + _kMCMExistingContainerReplaceError, + _kMCMFailureToGetErrorReply, + _kMCMGetMetadataErrorError, + _kMCMIdentifierNotFoundInDbError, + _kMCMInvalidCommandError, + _kMCMInvalidContainerObjectError, + _kMCMInvalidEntitlementInfoError, + _kMCMInvalidMetadataError, + _kMCMInvalidMetadataURLMismatchError, + _kMCMInvalidParametersError, + _kMCMInvalidReplyError, + _kMCMInvalidURLError, + _kMCMMismatchedClassReplaceError, + _kMCMMismatchedUserReplaceError, + _kMCMMoveStagingToLiveError, + _kMCMMoveToDeathRowError, + _kMCMNilIdentifierError, + _kMCMNotEntitledForOperationError, + _kMCMPathNotFoundError, + _kMCMPendingUpdateNoLongerValidError, + _kMCMReadEntitlementFileError, + _kMCMReadMetadataError, + _kMCMRegenerateUUIDMoveError, + _kMCMRemoveIndividualStagingDirectoryError, + _kMCMRemoveLegacyDirectoryError, + _kMCMRemoveStagingDirectoryError, + _kMCMRemoveTempContainerError, + _kMCMReplaceContainerError, + _kMCMReplaceMoveToTempError, + _kMCMReplaceRecoverError, + _kMCMReplaceRemoveError, + _kMCMReplaceURLError, + _kMCMRestoreContainerError, + _kMCMRestorePathExistsError, + _kMCMSQLiteError, + _kMCMSQLiteUnexpectedNumChangesError, + _kMCMSameContainerReplaceError, + _kMCMSetSandboxMappingError, + _kMCMSetupProxyError, + _kMCMStageForDeleteError, + _kMCMStageSharedContentFailureError, + _kMCMSuccess, + _kMCMUndefinedContainerClassError, + _kMCMUnknownSubdirectoriesForClassError, + _kMCMValueNotFoundForKeyError, + _kMCMWriteEntitlementFileError, + _kMCMWriteMetadataDictionaryError, + _kMCMXPCInterruptedReplyError, + _kMCMXPCInvalidReplyError, + _kMCMXPCSetupError, + _kMCMXPCUnknownReplyError ] + objc-classes: [ MCMAppContainer, + MCMAppDataContainer, + MCMContainer, + MCMContainerManager, + MCMDataContainer, + MCMFrameworkContainer, + MCMInternalDaemonDataContainer, + MCMPerUserAppContainer, + MCMPluginKitPluginContainer, + MCMPluginKitPluginDataContainer, + MCMSharedDataContainer, + MCMSharedSystemDataContainer, + MCMSystemDataContainer, + MCMTempDirDataContainer, + MCMVPNPluginContainer, + MCMVPNPluginDataContainer, + MCMXPCServiceDataContainer ] + objc-ivars: [ MCMContainer._containerClass, + MCMContainer._identifier, + MCMContainer._personaUniqueString, + MCMContainer._thisContainer, + MCMContainer._uuid ] ... diff --git a/man/uicache.1 b/man/uicache.1 index 94d96bc..e914b87 100644 --- a/man/uicache.1 +++ b/man/uicache.1 @@ -1,8 +1,8 @@ .\" -.\" Copyright (c) 2020-2023 ProcursusTeam +.\" Copyright (c) 2020-2024 ProcursusTeam .\" SPDX-License-Identifier: BSD-4-Clause .\" -.Dd January 29, 2023 +.Dd June 9, 2024 .Dt UICACHE 1 .Os .Sh NAME @@ -10,7 +10,7 @@ .Nd Update registered applications .Sh SYNOPSIS .Nm -.Op Fl afhlrv +.Op Fl afhlrvs .Op Fl i Ar id .Op Fl p Ar path .Op Fl u Ar path @@ -30,12 +30,6 @@ rather than just the changes. This option will make .Fl a significantly slower. -When used with -.Fl p -or -.Fl u , -.Nm -will operate on apps installed from the App Store. .It Fl h , -help Prints help text. .It Fl i , -info Ar bundleid diff --git a/man/zh_CN/uicache.1 b/man/zh_CN/uicache.1 index 08794c1..8b3db19 100644 --- a/man/zh_CN/uicache.1 +++ b/man/zh_CN/uicache.1 @@ -1,89 +1,85 @@ .\"- -.\" 版权所有 (c) 2020-2021 ProcursusTeam +.\" 版权所有 (c) 2020-2024 ProcursusTeam .\" SPDX-License-Identifier: BSD-4-Clause .\" -.Dd 2021年8月19日 +.Dd 2024年6月9日 .Dt UICACHE 1 .Os .Sh 名称 .Nm uicache -.Nd 更新已注册的应用程序 +.Nd 更新已注册的应用程式 .Sh 语法 .Nm -.Op Fl afhlr +.Op Fl afhlrvs .Op Fl i Ar 识别码 .Op Fl p Ar 路径 .Op Fl u Ar 路径 .Sh 描述 -更新iOS应用程序的注册状态,然后可选地重新启动主界面(SpringBoard)。 +更新iOS已注册的应用程式,然后可选地重新启动主画面。 .Sh 选项 .Bl -tag -width indent .It Fl a , -all -遍历每一个系统应用程序, 并更新缓存以及时映射更改。 +迭代每一个系统应用程式, 并更新快取以反映情况。 这和旧 .Nm -不添加任何选项的行为一样。 +的行为一样。 .It Fl f , -force 当和 .Fl a -同时使用时强制重新注册所有的应用程序,而不仅仅是被更改的应用程序。 +一起使用时, +强制重新注册所有的应用程式,而不是仅限于改变了的应用程式。 这个选项会导致 .Fl a 的速度明显减慢。 -当和 -.Fl p -或 -.Fl u , -.Nm -一起使用时,会作用在App Store应用程序上。 .It Fl h , -help -输出帮助文本。 -.It Fl i , -info Ar bundleid -显示指定Bundle ID的应用程序信息。 +印出帮助文本。 +.It Fl i , -info Ar 封装识别码 +显示指定封装识别码的应用程式资讯。 .It Fl l , -list -列出每一个应用程序的路径和Bundle ID。 +列出每一个应用程式的路径和封装识别码。 .It Fl p , -path Ar 路径 把位于指定 .Ar 路径 -, 中的应用程序加入或更新到缓存中。 +, 中的应用程式加入到快取中, 或更新快取。 .It Fl r , -respring -在完成所有操作之后,重新启动SpringBoard和backboard。 +在完成所有操作之后,重新启动主画面和backboard。 .It Fl u , -unregister Ar 路径 -从缓存中移除位于 +从快取中移除位于 .Ar 路径 -, 的应用程序。 +的应用程式。 +.It Fl s , -force-system +强行把应用程式注册为系统应用程式。 +.Pp +一般来说,当注册的应用程式位于/var/containers之中, +该应用程式会被注册为用户应用程式。 +使用这个选项时,无论应用程式是否位于/var/containers之中, +都会被注册为系统应用程式。 .It Fl v , -verbose 当和 .Fl a -一起使用时,输出被注册或被取消注册的应用程序。 +一起使用时,印出被注册或被取消注册的应用程式。 .El .Sh 例子 -刷新所有应用程序, +要重新整理所有应用程式, .Dl "uicache -a" .Pp -注册Sileo, +要注册Sileo, .Dl "uicache -p /Applications/Sileo.app" .Pp -要显示关于"设置"应用程序的资讯, +要显示关于「设定」应用程式的资讯, .Dl "uicache -i com.apple.preferences" .Sh 另见 .Xr sbreload 1 , .Xr uiopen 1 .Sh 历史 +这个 .Nm -工具首先在2008年9月14日于uikittools中出现,由 +工具程式首先在2008年9月14日在uikittools中出现,由 .An Jay Qo Saurik Qc Freeman 编写。 之后,它被 .An CoolStar -为Chimera越狱而重新实现。 +为Chimera越狱重新实现。 .Fl l 和 .Fl i 选项在2021年4月4号由Cameron Katri加到uikittools-ng中。 -.Sh 警告 -这个 -.Nm -工具对任何由App Store安装的应用程序生效, -这个工具会进行检查来防止对其进行改动,但仍然可以用 -.Fl f -来强制执行。 diff --git a/man/zh_TW/uicache.1 b/man/zh_TW/uicache.1 index 6c33de6..fe72ebe 100644 --- a/man/zh_TW/uicache.1 +++ b/man/zh_TW/uicache.1 @@ -2,7 +2,7 @@ .\" 版權所有 (c) 2020-2021 ProcursusTeam .\" SPDX-License-Identifier: BSD-4-Clause .\" -.Dd 2021年8月19日 +.Dd 2024年6月9日 .Dt UICACHE 1 .Os .Sh 名稱 @@ -10,7 +10,7 @@ .Nd 更新已註冊的應用程式 .Sh 語法 .Nm -.Op Fl afhlr +.Op Fl afhlrvs .Op Fl i Ar 識別碼 .Op Fl p Ar 路徑 .Op Fl u Ar 路徑 @@ -26,16 +26,11 @@ .It Fl f , -force 當和 .Fl a -強制重新註冊所有的應用程式,而不是改變。 +一起使用時, +強制重新註冊所有的應用程式,而不是僅限於改變了的應用程式。 這個選項會導致 .Fl a 的速度明顯減慢。 -當和 -.Fl p -或 -.Fl u , -.Nm -一起使用時,會作用在App Store應用程式上。 .It Fl h , -help 印出幫助文本。 .It Fl i , -info Ar 封裝識別碼 @@ -51,7 +46,14 @@ .It Fl u , -unregister Ar 路徑 從快取中移除位於 .Ar 路徑 -, 的應用程式。 +的應用程式。 +.It Fl s , -force-system +強行把應用程式註冊為系統應用程式。 +.Pp +一般來說,當註冊的應用程式位於/var/containers之中, +該應用程式會被註冊為用戶應用程式。 +使用這個選項時,無論應用程式是否位於/var/containers之中, +都會被註冊為系統應用程式。 .It Fl v , -verbose 當和 .Fl a @@ -81,10 +83,3 @@ 和 .Fl i 選項在2021年4月4號由Cameron Katri加到uikittools-ng中。 -.Sh 警告 -這個 -.Nm -工具程式不會工作在任何由App Store安裝的應用程式, -這個工具程式有一個檢查來防止改動但可以用 -.Fl f -來強制執行。 diff --git a/sbreload.plist b/sbreload.plist index 8e2e495..b3dfc6d 100644 --- a/sbreload.plist +++ b/sbreload.plist @@ -13,5 +13,7 @@ com.apple.appletv.pbs.allow-relaunch + com.apple.private.xpc.service-configure + diff --git a/uicache.m b/uicache.m index fcb899e..a83cd26 100644 --- a/uicache.m +++ b/uicache.m @@ -155,62 +155,71 @@ SecStaticCodeRef getStaticCodeRef(NSString *binaryPath) { if (binaryPath == nil) { return NULL; } - + CFURLRef binaryURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, (__bridge CFStringRef)binaryPath, kCFURLPOSIXPathStyle, false); if (binaryURL == NULL) { return NULL; } - + SecStaticCodeRef codeRef = NULL; OSStatus result; - + result = SecStaticCodeCreateWithPathAndAttributes(binaryURL, kSecCSDefaultFlags, NULL, &codeRef); - + CFRelease(binaryURL); - + if (result != errSecSuccess) { return NULL; } - + return codeRef; } -NSDictionary *dumpEntitlements(SecStaticCodeRef codeRef) { - if (codeRef == NULL) { +NSDictionary* dumpEntitlements(SecStaticCodeRef codeRef) +{ + if(codeRef == NULL) + { return nil; } - + CFDictionaryRef signingInfo = NULL; OSStatus result; - + result = SecCodeCopySigningInformation(codeRef, kSecCSRequirementInformation, &signingInfo); - - if (result != errSecSuccess) { + + if(result != errSecSuccess) + { return nil; } - + NSDictionary *entitlementsNSDict = nil; - CFDictionaryRef entitlements = CFDictionaryGetValue(signingInfo, kSecCodeInfoEntitlementsDict); - if (entitlements) { - if (CFGetTypeID(entitlements) == CFDictionaryGetTypeID()) { - entitlementsNSDict = (__bridge NSDictionary *)(entitlements); - } + + if (entitlements) { + if (CFGetTypeID(entitlements) == CFDictionaryGetTypeID()) { + entitlementsNSDict = (__bridge NSDictionary *)(entitlements); + } } + CFRelease(signingInfo); return entitlementsNSDict; } -NSDictionary *dumpEntitlementsFromBinaryAtPath(NSString *binaryPath) { - if (binaryPath == nil) { +NSDictionary* dumpEntitlementsFromBinaryAtPath(NSString *binaryPath) +{ + // This function is intended for one-shot checks. Main-event functions should retain/release their own SecStaticCodeRefs + + if (binaryPath == nil) + { return nil; } - + SecStaticCodeRef codeRef = getStaticCodeRef(binaryPath); - if (codeRef == NULL) { + if (codeRef == NULL) + { return nil; } - + NSDictionary *entitlements = dumpEntitlements(codeRef); CFRelease(codeRef); @@ -248,24 +257,6 @@ SecStaticCodeRef getStaticCodeRef(NSString *binaryPath) { return nil; } -BOOL constructContainerizationForEntitlements(NSDictionary *entitlements) { - NSNumber *noContainer = entitlements[@"com.apple.private.security.no-container"]; - if (noContainer && [noContainer isKindOfClass:[NSNumber class]]) { - if (noContainer.boolValue) { - return NO; - } - } - - NSNumber *containerRequired = entitlements[@"com.apple.private.security.container-required"]; - if (containerRequired && [containerRequired isKindOfClass:[NSNumber class]]) { - if (!containerRequired.boolValue) { - return NO; - } - } - - return YES; -} - NSString *constructTeamIdentifierForEntitlements(NSDictionary *entitlements) { NSString *teamIdentifier = entitlements[@"com.apple.developer.team-identifier"]; if (teamIdentifier && [teamIdentifier isKindOfClass:[NSString class]]) { @@ -284,8 +275,31 @@ BOOL constructContainerizationForEntitlements(NSDictionary *entitlements) { }; } -void registerPath(NSString *path, BOOL unregister, BOOL forceSystem) { - if (!path) return; + + +BOOL constructContainerizationForEntitlements(NSDictionary *entitlements, NSString **customContainerOut) { + NSNumber *noContainer = entitlements[@"com.apple.private.security.no-container"]; + if (noContainer && [noContainer isKindOfClass:[NSNumber class]]) { + if (noContainer.boolValue) { + return NO; + } + } + + NSObject *containerRequired = entitlements[@"com.apple.private.security.container-required"]; + if (containerRequired && [containerRequired isKindOfClass:[NSNumber class]]) { + if (!((NSNumber *)containerRequired).boolValue) { + return NO; + } + } + else if (containerRequired && [containerRequired isKindOfClass:[NSString class]]) { + *customContainerOut = (NSString *)containerRequired; + } + + return YES; +} + +bool registerPath(NSString *path, BOOL unregister, BOOL forceSystem) { + if (!path) return false; LSApplicationWorkspace *workspace = [LSApplicationWorkspace defaultWorkspace]; if (unregister && ![[NSFileManager defaultManager] fileExistsAtPath:path]) { @@ -301,8 +315,14 @@ void registerPath(NSString *path, BOOL unregister, BOOL forceSystem) { NSString *appBundleID = [appInfoPlist objectForKey:@"CFBundleIdentifier"]; if (appBundleID && !unregister) { - MCMContainer *appContainer = [NSClassFromString(@"MCMAppDataContainer") containerWithIdentifier:appBundleID createIfNecessary:YES existed:nil error:nil]; - NSString *containerPath = [appContainer url].path; + NSString *appExecutablePath = [path stringByAppendingPathComponent:appInfoPlist[@"CFBundleExecutable"]]; + NSDictionary *entitlements = dumpEntitlementsFromBinaryAtPath(appExecutablePath); + + NSString *appDataContainerID = appBundleID; + BOOL appContainerized = constructContainerizationForEntitlements(entitlements, &appDataContainerID); + + MCMContainer *appDataContainer = [NSClassFromString(@"MCMAppDataContainer") containerWithIdentifier:appDataContainerID createIfNecessary:YES existed:nil error:nil]; + NSString *containerPath = [appDataContainer url].path; BOOL isRemovableSystemApp = [[NSFileManager defaultManager] fileExistsAtPath:[@"/System/Library/AppSignatures" stringByAppendingPathComponent:appBundleID]]; BOOL registerAsUser = [path hasPrefix:@"/var/containers"] && !isRemovableSystemApp && !forceSystem; @@ -311,20 +331,17 @@ void registerPath(NSString *path, BOOL unregister, BOOL forceSystem) { // Add entitlements - NSString *appExecutablePath = [path stringByAppendingPathComponent:appInfoPlist[@"CFBundleExecutable"]]; - NSDictionary *entitlements = dumpEntitlementsFromBinaryAtPath(appExecutablePath); if (entitlements) { dictToRegister[@"Entitlements"] = entitlements; } - // Misc - + dictToRegister[@"ApplicationType"] = registerAsUser ? @"User" : @"System"; + dictToRegister[@"BundleNameIsLocalized"] = @1; dictToRegister[@"CFBundleIdentifier"] = appBundleID; dictToRegister[@"CodeInfoIdentifier"] = appBundleID; dictToRegister[@"CompatibilityState"] = @0; - BOOL appContainerized = constructContainerizationForEntitlements(entitlements); dictToRegister[@"IsContainerized"] = @(appContainerized); if (containerPath) { dictToRegister[@"Container"] = containerPath; @@ -332,7 +349,7 @@ void registerPath(NSString *path, BOOL unregister, BOOL forceSystem) { } dictToRegister[@"IsDeletable"] = @(registerAsUser || isRemovableSystemApp); dictToRegister[@"Path"] = path; - + dictToRegister[@"SignerOrganization"] = @"Apple Inc."; dictToRegister[@"SignatureVersion"] = @132352; dictToRegister[@"SignerIdentity"] = @"Apple iPhone OS Application Signing"; @@ -376,15 +393,17 @@ void registerPath(NSString *path, BOOL unregister, BOOL forceSystem) { NSString *pluginBundleID = [pluginInfoPlist objectForKey:@"CFBundleIdentifier"]; if (!pluginBundleID) continue; - MCMContainer *pluginContainer = [NSClassFromString(@"MCMPluginKitPluginDataContainer") containerWithIdentifier:pluginBundleID createIfNecessary:YES existed:nil error:nil]; + NSString *pluginExecutablePath = [pluginPath stringByAppendingPathComponent:pluginInfoPlist[@"CFBundleExecutable"]]; + NSDictionary *pluginEntitlements = dumpEntitlementsFromBinaryAtPath(pluginExecutablePath); + NSString *pluginDataContainerID = pluginBundleID; + BOOL pluginContainerized = constructContainerizationForEntitlements(pluginEntitlements, &pluginDataContainerID); + + MCMContainer *pluginContainer = [NSClassFromString(@"MCMPluginKitPluginDataContainer") containerWithIdentifier:pluginDataContainerID createIfNecessary:YES existed:nil error:nil]; NSString *pluginContainerPath = [pluginContainer url].path; NSMutableDictionary *pluginDict = [NSMutableDictionary dictionary]; // Add entitlements - - NSString *pluginExecutablePath = [pluginPath stringByAppendingPathComponent:pluginInfoPlist[@"CFBundleExecutable"]]; - NSDictionary *pluginEntitlements = dumpEntitlementsFromBinaryAtPath(pluginExecutablePath); if (pluginEntitlements) { pluginDict[@"Entitlements"] = pluginEntitlements; } @@ -395,7 +414,7 @@ void registerPath(NSString *path, BOOL unregister, BOOL forceSystem) { pluginDict[@"CFBundleIdentifier"] = pluginBundleID; pluginDict[@"CodeInfoIdentifier"] = pluginBundleID; pluginDict[@"CompatibilityState"] = @0; - BOOL pluginContainerized = constructContainerizationForEntitlements(pluginEntitlements); + pluginDict[@"IsContainerized"] = @(pluginContainerized); if (pluginContainerPath) { pluginDict[@"Container"] = pluginContainerPath; @@ -437,13 +456,16 @@ void registerPath(NSString *path, BOOL unregister, BOOL forceSystem) { if (![workspace registerApplicationDictionary:dictToRegister]) { fprintf(stderr, _("Error: Unable to register %s\n"), path.fileSystemRepresentation); + return false; } } else { NSURL *url = [NSURL fileURLWithPath:path]; if (![workspace unregisterApplication:url]) { fprintf(stderr, _("Error: Unable to unregister %s\n"), path.fileSystemRepresentation); + return false; } } + return true; } void listBundleID(void) { @@ -510,7 +532,7 @@ void registerAll(void) { NSDictionary *infoPlist = [NSDictionary dictionaryWithContentsOfURL:infoPlistURL error:nil]; if (infoPlist) { if (infoPlist[@"CFBundleExecutable"]) { - [installedAppURLs addObject:appURL]; + [installedAppURLs addObject:appURL.URLByStandardizingPath]; } } }; @@ -529,7 +551,7 @@ void registerAll(void) { for (LSApplicationProxy *app in [workspace allApplications]) { NSString *appPath = [app bundleURL].path; if ([appPath hasPrefix:@"/Applications"] || [appPath hasPrefix:APP_PATH] || [appPath hasPrefix:secondaryApps]) { - [registeredAppURLs addObject:[app bundleURL]]; + [registeredAppURLs addObject:[app bundleURL].URLByStandardizingPath]; } } @@ -568,7 +590,7 @@ int main(int argc, char *argv[]) { struct option longOptions[] = { {"all", no_argument, 0, 'a'}, {"path", required_argument, 0, 'p'}, - {"force-system", no_argument, 0, 's'}, + {"force-system", no_argument, 0, 's'}, {"unregister", required_argument, 0, 'u'}, {"respring", no_argument, 0, 'r'}, {"list", optional_argument, 0, 'l'},