Ver código fonte

ditto all my other commit messages

Kevin Bradley 8 anos atrás
pai
commit
cb91aecbd8
11 arquivos alterados com 501 adições e 65 exclusões
  1. 2 1
      AppEnabler/Makefile
  2. 109 1
      AppEnabler/Whitelist.xm
  3. 34 1
      AppEnabler/main.x
  4. 10 5
      Makefile
  5. 298 49
      PBReloadHelper.m
  6. 2 2
      control
  7. 5 3
      main.m
  8. BIN
      theos/vendor/lib/libsubstrate.dylib
  9. 1 1
      uicache/Makefile
  10. 33 2
      uicache/uicache.m
  11. 7 0
      uicache/uicache.xml

+ 2 - 1
AppEnabler/Makefile

@@ -7,11 +7,12 @@ THEOS_DEVICE_IP=atv.local
 include $(THEOS)/makefiles/common.mk
 include $(THEOS)/makefiles/common.mk
 
 
 TWEAK_NAME = AppEnabler
 TWEAK_NAME = AppEnabler
-AppEnabler_FILES = main.x Whitelist.xm
+AppEnabler_FILES = main.x Whitelist.xm ../PBReloadHelper.m
 AppEnabler_LIBRARIES = substrate
 AppEnabler_LIBRARIES = substrate
 AppEnabler_FRAMEWORKS = Foundation UIKit CoreGraphics MobileCoreServices
 AppEnabler_FRAMEWORKS = Foundation UIKit CoreGraphics MobileCoreServices
 AppEnabler_LDFLAGS = -undefined dynamic_lookup
 AppEnabler_LDFLAGS = -undefined dynamic_lookup
 #AppEnabler_LIBRARIES += rocketbootstrap
 #AppEnabler_LIBRARIES += rocketbootstrap
+#AppEnabler_CODESIGN_FLAGS=-Slibrespring.xml
 
 
 include $(THEOS_MAKE_PATH)/tweak.mk
 include $(THEOS_MAKE_PATH)/tweak.mk
 
 

+ 109 - 1
AppEnabler/Whitelist.xm

@@ -1,5 +1,113 @@
+#import "NSTask.h"
+
+#define  CORE_SERVICE_FRAMEWORK  "/System/Library/Frameworks/MobileCoreServices.framework/MobileCoreServices"
+@interface LSApplicationWorkspace: NSObject
+- (id)allApplications;
+- (void)openApplicationWithBundleID:(NSString *)string;
+- (id)defaultWorkspace;
+@end
+
+%hook PBApplication
+
+%new - (void)openApp:(NSString *)bundleID {
+    
+    %log;
+    id workspace = nil;
+    Class LSApplicationWorkspace_class = objc_getClass("LSApplicationWorkspace");
+    if (!LSApplicationWorkspace_class) {
+        
+        fprintf(stderr,"Unable to get Workspace class\n");
+        
+    }
+    
+    workspace = [LSApplicationWorkspace_class performSelector:@selector (defaultWorkspace)];
+    if (!workspace) {fprintf(stderr,"Unable to get Workspace\n"); }
+    /*
+     void *CS_handle = dlopen (CORE_SERVICE_FRAMEWORK, RTLD_NOW);
+     if (!CS_handle) {
+     fprintf(stderr,"Can't find %s!\n", CORE_SERVICE_FRAMEWORK);
+     return;
+     }
+     */
+    if (workspace){
+        [workspace performSelector:@selector(openApplicationWithBundleID:) withObject:(id) bundleID ];
+    }
+    
+    
+}
+
+
+- (void)finishSystemAppLaunch {
+    
+    %log;
+    %orig;
+    NSFileManager *man = [NSFileManager defaultManager];
+    NSString *nl = @"/var/mobile/Library/Preferences/.nitolaunch";
+    if ([man fileExistsAtPath:nl]){
+        NSLog(@"launch nitoTV");
+        
+        [self openApp:@"com.nito.nitoTV4"];
+        [man removeItemAtPath:nl error:nil];
+        //[NSTask launchedTaskWithLaunchPath:@"/usr/bin/uicache" arguments:@[]];
+    }
+    
+    
+}
+
+%end
+
+%hook PBAppDelegate
+
+%new - (void)openApp:(NSString *)bundleID {
+    
+    id workspace = nil;
+    Class LSApplicationWorkspace_class = objc_getClass("LSApplicationWorkspace");
+    if (!LSApplicationWorkspace_class) {
+        
+        fprintf(stderr,"Unable to get Workspace class\n");
+        
+    }
+    
+    workspace = [LSApplicationWorkspace_class performSelector:@selector (defaultWorkspace)];
+    if (!workspace) {fprintf(stderr,"Unable to get Workspace\n"); }
+    /*
+    void *CS_handle = dlopen (CORE_SERVICE_FRAMEWORK, RTLD_NOW);
+    if (!CS_handle) {
+        fprintf(stderr,"Can't find %s!\n", CORE_SERVICE_FRAMEWORK);
+        return;
+    }
+    */
+    if (workspace){
+        [workspace performSelector:@selector(openApplicationWithBundleID:) withObject:(id) bundleID ];
+    }
+    
+    
+}
+
+- (_Bool)application:(id)arg1 didFinishLaunchingWithOptions:(id)arg2 {
+    
+    _Bool orig = %orig;
+    %log;
+    NSFileManager *man = [NSFileManager defaultManager];
+    NSString *kickstartPath = @"/var/mobile/Library/Preferences/.kickstart";
+    if ([man fileExistsAtPath:kickstartPath]){
+        NSLog(@"kickstart");
+        
+         //[self openApp:@"com.nito.nitoTV4"];
+        [man removeItemAtPath:kickstartPath error:nil];
+        [NSTask launchedTaskWithLaunchPath:@"/usr/bin/uicache" arguments:@[]];
+        [FM createFileAtPath:@"/var/mobile/Library/Preferences/.nitolaunch" contents:[@"" dataUsingEncoding:NSASCIIStringEncoding] attributes:nil];
+    }
+    return orig;
+    
+}
+
+%end
+
 %hook PBSMutableAppState
 %hook PBSMutableAppState
 
 
+
+
 -(BOOL)isEnabled
 -(BOOL)isEnabled
 {
 {
     //%log;
     //%log;
@@ -18,7 +126,7 @@
     }
     }
     if ([whitelistArray containsObject:ourID] && ![deletedArray containsObject:ourID])
     if ([whitelistArray containsObject:ourID] && ![deletedArray containsObject:ourID])
     {
     {
-        NSLog(@"whitelisted: %@",ourID );
+        //NSLog(@"whitelisted: %@",ourID );
         return YES;
         return YES;
     } else {
     } else {
         return NO;
         return NO;

+ 34 - 1
AppEnabler/main.x

@@ -12,6 +12,31 @@
 #import <objc/runtime.h>
 #import <objc/runtime.h>
 //#import "rocketbootstrap.h"
 //#import "rocketbootstrap.h"
 //#import "AppSupport/CPDistributedMessagingCenter.h"
 //#import "AppSupport/CPDistributedMessagingCenter.h"
+#import "../PBReloadHelper.h"
+#import <Foundation/Foundation.h>
+#import "AppSupport/CPDistributedMessagingCenter.h"
+
+@interface NSDistributedNotificationCenter : NSNotificationCenter
+
++ (id)defaultCenter;
+
+- (void)addObserver:(id)arg1 selector:(SEL)arg2 name:(id)arg3 object:(id)arg4;
+- (void)postNotificationName:(id)arg1 object:(id)arg2 userInfo:(id)arg3;
+
+@end
+
+@interface MessageHandler : NSObject
+-(void)runAppEnabler:(id)a;
+@end
+@implementation MessageHandler
+
+-(void)runAppEnabler:(id)a
+{
+    //NSLog(@"#### for luck!");
+    [PBReloadHelper reloadApplications];
+}
+
+@end
 
 
 %class LSContext
 %class LSContext
 %class FSNode
 %class FSNode
@@ -138,6 +163,7 @@ id we_really_out_here(uint64_t a, uint64_t (^block)(id b1, uint64_t b2, uint64_t
 
 
 %ctor
 %ctor
 {
 {
+    
 	dlopen("/System/Library/PrivateFrameworks/MobileInstallation.framework/MobileInstallation", RTLD_LAZY);
 	dlopen("/System/Library/PrivateFrameworks/MobileInstallation.framework/MobileInstallation", RTLD_LAZY);
 	
 	
 	MSImageRef gangshit = MSGetImageByName("/System/Library/PrivateFrameworks/MobileInstallation.framework/MobileInstallation");
 	MSImageRef gangshit = MSGetImageByName("/System/Library/PrivateFrameworks/MobileInstallation.framework/MobileInstallation");
@@ -163,6 +189,13 @@ id we_really_out_here(uint64_t a, uint64_t (^block)(id b1, uint64_t b2, uint64_t
         //void (*lolz)() = weouthere;
         //void (*lolz)() = weouthere;
         //lolz();
         //lolz();
     }
     }
-
     
     
+    //NSLog(@"before note center");
+    
+    NSDistributedNotificationCenter* notificationCenter = [NSDistributedNotificationCenter defaultCenter];
+    
+    //NSLog(@"after note center");
+    [notificationCenter addObserver:[MessageHandler new]  selector:@selector(runAppEnabler:) name:@"kjc.AppEnabler.recache" object:nil];
+
+    // NSLog(@"after observe");
 } 
 } 

+ 10 - 5
Makefile

@@ -1,8 +1,10 @@
 ARCHS=arm64
 ARCHS=arm64
 TARGET=appletv
 TARGET=appletv
 export GO_EASY_ON_ME=1
 export GO_EASY_ON_ME=1
-export SDKVERSION=10.2
-THEOS_DEVICE_IP=apple-tv.local
+export SDKVERSION=10.1
+TARGET=appletv:clang:10.1:10.1
+SYSROOT=/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS10.1.sdk
+THEOS_DEVICE_IP=atv11.local
 
 
 include theos/makefiles/common.mk
 include theos/makefiles/common.mk
 
 
@@ -11,19 +13,22 @@ librespring_FILES = main.m PBReloadHelper.m
 librespring_LIBRARIES = substrate
 librespring_LIBRARIES = substrate
 #librespring_LIBRARIES += rocketbootstrap
 #librespring_LIBRARIES += rocketbootstrap
 librespring_FRAMEWORKS = Foundation UIKit CoreGraphics
 librespring_FRAMEWORKS = Foundation UIKit CoreGraphics
+#librespring_CODESIGN_FLAGS=-Slibrespring.xml
 librespring_Frameworks += WebCore ImageIO Foundation CFNetwork AppSupport UIKit IOKit MobileCoreServices
 librespring_Frameworks += WebCore ImageIO Foundation CFNetwork AppSupport UIKit IOKit MobileCoreServices
-librespring_PRIVATE_FRAMEWORKS = GraphicsServices FMCore
+#librespring_PRIVATE_FRAMEWORKS = GraphicsServices FMCore
 
 
 include $(THEOS_MAKE_PATH)/library.mk
 include $(THEOS_MAKE_PATH)/library.mk
 
 
 SUBPROJECTS += uicache
 SUBPROJECTS += uicache
 SUBPROJECTS += AppEnabler
 SUBPROJECTS += AppEnabler
+#SUBPROJECTS += libsubstrate
+
 include $(THEOS_MAKE_PATH)/aggregate.mk
 include $(THEOS_MAKE_PATH)/aggregate.mk
 
 
 after-stage::
 after-stage::
 	#cp $(FW_STAGING_DIR)/usr/bin/uicache ../layout/usr/bin/uicache
 	#cp $(FW_STAGING_DIR)/usr/bin/uicache ../layout/usr/bin/uicache
-	#cp $(FW_STAGING_DIR)/Library/MobileSubstrate/DynamicLibraries/AppEnabler.dylib ../layout/Library/MobileSubstrate/DynamicLibraries/AppEnabler.dylib
-	#cp $(FW_STAGING_DIR)/Library/MobileSubstrate/DynamicLibraries/AppEnabler.plist ../layout/Library/MobileSubstrate/DynamicLibraries/AppEnabler.plist
+	#cp $(FW_STAGING_DIR)/Library/TweakInject/AppEnabler.dylib ../layout/Library/TweakInject/AppEnabler.dylib
+	#cp $(FW_STAGING_DIR)/Library/TweakInject/AppEnabler.plist ../layout/Library/TweakInject/AppEnabler.plist
 	#cp $(FW_STAGING_DIR)/usr/lib/librespring.dylib ../layout/usr/lib/librespring.dylib
 	#cp $(FW_STAGING_DIR)/usr/lib/librespring.dylib ../layout/usr/lib/librespring.dylib
 	cp rmcache $(THEOS_STAGING_DIR)/usr/bin/
 	cp rmcache $(THEOS_STAGING_DIR)/usr/bin/
 	#cp rmcache ../layout/usr/bin/rmcache
 	#cp rmcache ../layout/usr/bin/rmcache

+ 298 - 49
PBReloadHelper.m

@@ -92,11 +92,11 @@
 /**
 /**
  
  
  On tvOS 10+ we need to manually remove the applications from PBAppDepot after moving / removing
  On tvOS 10+ we need to manually remove the applications from PBAppDepot after moving / removing
- them from the /var/mobile/Applications folder. This method cycles filters allInstalledApplications 
+ them from the /var/mobile/Applications folder. This method cycles filters allInstalledApplications
  in the application workspace to only applications with the bundleURL string containing
  in the application workspace to only applications with the bundleURL string containing
  /var/mobile/Applications/
  /var/mobile/Applications/
  
  
- loop through them and see which ones actually exist, if they dont, add the bundle ID to the 
+ loop through them and see which ones actually exist, if they dont, add the bundle ID to the
  deleted array that is returned.
  deleted array that is returned.
  
  
  */
  */
@@ -114,7 +114,7 @@
     __block BOOL containsApplication = NO;
     __block BOOL containsApplication = NO;
     NSArray *installedApplications = [workspace allInstalledApplications];
     NSArray *installedApplications = [workspace allInstalledApplications];
     
     
-    NSPredicate *pred = [NSPredicate predicateWithFormat:@"self.bundleURL.absoluteString contains[cd] %@ or self.applicationIdentifier contains[cd] %@ ", @"/var/mobile/Applications/", @"com.nito.nitoTV4"];
+    NSPredicate *pred = [NSPredicate predicateWithFormat:@"self.bundleURL.absoluteString contains[cd] %@ or self.applicationIdentifier contains[cd] %@ ", @"/Applications/", @"com.nito.nitoTV4"];
     NSArray <LSApplicationProxy *> *mobileApplications = [installedApplications filteredArrayUsingPredicate:pred];
     NSArray <LSApplicationProxy *> *mobileApplications = [installedApplications filteredArrayUsingPredicate:pred];
     //NSLog(@"new array: %@", newArray);
     //NSLog(@"new array: %@", newArray);
     
     
@@ -161,7 +161,7 @@
     __block NSMutableArray *deletedArray = [NSMutableArray new];
     __block NSMutableArray *deletedArray = [NSMutableArray new];
     NSArray *installedApplications = [workspace allInstalledApplications];
     NSArray *installedApplications = [workspace allInstalledApplications];
     
     
-    NSPredicate *pred = [NSPredicate predicateWithFormat:@"self.bundleURL.absoluteString contains[cd] %@ or self.applicationIdentifier contains[cd] %@ ", @"/var/mobile/Applications/", @"com.nito.nitoTV4"];
+    NSPredicate *pred = [NSPredicate predicateWithFormat:@"self.bundleURL.absoluteString contains[cd] %@ or self.applicationIdentifier contains[cd] %@ ", @"/Applications/", @"com.nito.nitoTV4"];
     NSArray <LSApplicationProxy *> *mobileApplications = [installedApplications filteredArrayUsingPredicate:pred];
     NSArray <LSApplicationProxy *> *mobileApplications = [installedApplications filteredArrayUsingPredicate:pred];
     //NSLog(@"new array: %@", newArray);
     //NSLog(@"new array: %@", newArray);
     
     
@@ -184,8 +184,251 @@
     return deletedArray;
     return deletedArray;
 }
 }
 
 
++ (void)newReloadApplications {
+    
+    NSFileManager *manager = [NSFileManager defaultManager];
+    NSString *whichKill = @"/tmp/usr/bin/killall";
+    if (![manager fileExistsAtPath:whichKill])
+    {
+        whichKill = @"/usr/bin/killall";
+    }
+    
+    id appDepot = [objc_getClass("PBAppDepot") sharedInstance];
+    HBLogInfo(@"appDepot: %@", appDepot);
+    NSMutableDictionary *installedAppStates = [appDepot internalAppState];
+    NSLog(@"installedAppStates: %@", installedAppStates);
+    id nitoTV = [installedAppStates objectForKey:@"com.nito.nitoTV4"];
+    NSError *error = nil;
+    NSString *whitelistFile = @"/var/mobile/Library/Preferences/com.nito.whitelist.plist";
+    NSString *recentlyDeleted = @"/var/mobile/Library/Preferences/com.nito.deleted.plist";
+    NSArray *whiteList = [NSArray arrayWithContentsOfFile:whitelistFile];
+    if (!whiteList) {
+        
+        whiteList = @[@"com.nito.nitoTV4"];
+    }
+    NSMutableArray *recentDeletions = [NSMutableArray new];
+    NSMutableArray *mutableWhiteList = [whiteList mutableCopy];
+    BOOL addNito = [manager fileExistsAtPath:@"/Applications/nitoTV.app/nitoTV"];
+    
+    
+    NSMutableArray *appArray = [NSMutableArray new];
+    NSMutableArray *identifierArray = [NSMutableArray new];
+    BOOL addedApps = FALSE;
+    NSArray *apps = [manager contentsOfDirectoryAtPath:@"/Applications" error:&error];
+    
+    for (NSString *app in apps)
+        if ([app hasSuffix:@".app"]) {
+            
+            NSString *path = [@"/Applications" stringByAppendingPathComponent:app];
+            NSString *newPl = [path stringByAppendingPathComponent:@"Info.plist"];
+            NSMutableDictionary *info = [NSMutableDictionary dictionaryWithContentsOfFile:newPl];
+            
+            NSString *identifier = [info objectForKey:@"CFBundleIdentifier"];
+            
+            NSLog(@"identifier: %@", identifier);
+            
+            id existingObject = (PBSMutableAppState*)[installedAppStates objectForKey:identifier];
+            if (existingObject != nil)
+            {
+                //[installedAppStates setObject:existingObject forKey:identifier];
+                
+                if (![existingObject isEnabled]){
+                    
+                    NSLog(@"its disabled: %@", existingObject);
+                    if (![mutableWhiteList containsObject:identifier])
+                    {
+                        [mutableWhiteList addObject:identifier];
+                    }
+                    
+                    
+                    NSDictionary *appDict = @{@"ApplicationType": @"System", @"CFBundleIdentifier": identifier, @"CodeInfoIdentifier": identifier, @"Path": path};
+                    
+                    [appArray addObject:appDict];
+                    [identifierArray addObject:identifier];
+                    addedApps = YES;
+                    
+                }
+                
+            } else {
+                
+                
+                NSLog(@"didnt find object for key: %@", identifier);
+                if (![mutableWhiteList containsObject:identifier])
+                {
+                    [mutableWhiteList addObject:identifier];
+                }
+                
+                
+                NSDictionary *appDict = @{@"ApplicationType": @"System", @"CFBundleIdentifier": identifier, @"CodeInfoIdentifier": identifier, @"Path": path};
+                
+                [appArray addObject:appDict];
+                [identifierArray addObject:identifier];
+                addedApps = YES;
+                
+                
+                /*
+                 
+                 
+                 Class PBSMASC = objc_getClass("PBSMutableAppState");
+                 id appState = [[PBSMASC alloc] initWithApplicationIdentifer:identifier];
+                 [appState setEnabled:YES];
+                 //[appState setCacheDeleting:YES];
+                 [appState incrementCacheDeleting];
+                 NSLog(@"app state: %@", appState);
+                 [installedAppStates setObject:appState forKey:identifier];
+                 
+                 [workspace registerApplicationDictionary:info];
+                 
+                 */
+                
+            }
+            
+            
+            
+            
+            
+            
+            
+        }
+    
+    
+    NSString* pth = @"/var/mobile/Library/Preferences/kjc.appenabler.state.plist";
+    [appArray writeToFile:pth atomically:YES];
+    
+    Class WSCLASS = objc_getClass("LSApplicationWorkspace");
+    
+    id workspace = nil;
+    if (WSCLASS != nil)
+    {
+        workspace = [WSCLASS defaultWorkspace];
+    }
+    
+    
+    
+    
+    NSArray *deletedApps = [self deletedApplications];
+    BOOL removedApps = ([deletedApps count] > 0);
+    
+    if ([workspace respondsToSelector:@selector(_LSPrivateSyncWithMobileInstallation)]){
+        if (addedApps || removedApps){
+            
+            //rm /var/containers/Data/System/97D6E4BA-C0BF-408B-AF63-1836844381AE/Library/Caches/com.apple.LaunchServices-175-v2.csstore
+            
+            //delete the csstore file, its run through bash so the wildcards are completed properly
+            
+            //[NSTask launchedTaskWithLaunchPath:@"/bin/bash" arguments:@[@"/bin/rm", @"/var/containers/Data/System/*/Library/Caches/com.apple.LaunchServices*.csstore"]];
+            
+            //FIXME: i dont like calling this chmod +x shell script
+            //its probably a security risk of some type, but the line above
+            //didnt work properly and i couldnt figure out why
+            
+            [NSTask launchedTaskWithLaunchPath:@"/bin/bash" arguments:@[@"/usr/bin/rmcache"]];
+            
+            if (removedApps)
+            {
+                
+                NSLog(@"app ids were deleted: %@", deletedApps);
+                [deletedApps enumerateObjectsUsingBlock:^(NSString *  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+                    
+                    [mutableWhiteList removeObject:obj];
+                    [recentDeletions addObject:obj];
+                    NSLog(@"removing app state with id: %@", obj);
+                    [appDepot _removeAppStateForIdentifier:obj];
+                    
+                    
+                    
+                }];
+            } else {
+                //no removed apps, need to make sure they don't mess with our reload anymore
+                [[NSFileManager defaultManager] removeItemAtPath:recentlyDeleted error:nil];
+            }
+            
+            
+            
+            /*
+             
+             _LSPrivateSyncWithMobileInstallation will actually display the application and allow you to launch it, but the AppDepot (or something related to the installed app database) is potentially harshed or out of sync after we do this, which is why we always call the killall at the very bottom of this method, also if apps are
+             deleted their state is not updated properly without a respring either
+             
+             */
+            
+            
+            if((addedApps || removedApps)){
+                
+                NSLog(@"we can haz new app");
+                
+            }
+            
+        }
+        [workspace _LSClearSchemaCaches]; //may or may not be necessary
+        [workspace _LSPrivateRebuildApplicationDatabasesForSystemApps:YES internal:YES user:YES];
+        [workspace _LSPrivateSyncWithMobileInstallation];
+        [workspace invalidateIconCache:nil];
+    }
+    
+    [mutableWhiteList writeToFile:whitelistFile atomically:YES];
+    
+    [recentDeletions writeToFile:recentlyDeleted atomically:YES];
+    
+    if(addedApps){
+        
+        NSLog(@"we can haz new app");
+        
+        sleep(5);
+        
+        
+        for (NSDictionary* o in appArray)
+        {
+            char retry=0;
+            NSString* identifier = o[@"CFBundleIdentifier"];
+        retry_:
+            NSLog(@"identifier: %@", identifier);
+            
+            id existingObject = [installedAppStates objectForKey:identifier];
+            if (existingObject != nil)
+            {
+                [existingObject setValue:[NSNumber numberWithBool:YES] forKey:@"_enabled"];
+                BOOL isEnabled = [existingObject isEnabled];
+                
+                //[existingObject setEnabled:YES];
+                //[installedAppStates setObject: existingObject forKey: identifier];
+            } else {
+                //[appDepot _addAppStateForIdentifier:identifier];
+                NSLog(@"didnt find object for key: %@, error!!!!!!", identifier);
+                if(retry == 0)
+                {
+                    NSLog(@"retry");
+                    //NSLog(@"try to manually kick start substrate!");
+                    //[NSTask launchedTaskWithLaunchPath:@"/usr/bin/nitoHelper" arguments:@[@"substrate", @"1", @"2"]];
+                    //is9 = false;
+                    
+                    ///usr/bin/cynject 1 /Library/Frameworks/CydiaSubstrate.framework/Libraries/SubstrateLauncher.dylib
+                    retry = 1;
+                    goto retry_;
+                }
+            }
+        }
+    }
+    //this notification is received by uicache binary so its knows that its safe to exit the runloop it creates so it can relay notifications back and forth during this convoluted process.
+    
+    [[NSDistributedNotificationCenter defaultCenter] postNotificationName:@"kjc.AppEnabler.done" object:nil userInfo:nil];
+    
+    //it beats killall -u mobile... right?
+    //we dont have system() call anymore and posix_spawn is a pain to configure.
+    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
+        
+        //[@"science" writeToFile:@"/var/mobile/Library/Preferences/itshappening" atomically:YES encoding:NSUTF8StringEncoding error:nil];
+        
+        [NSTask launchedTaskWithLaunchPath:whichKill arguments:@[@"-9", @"PineBoard", @"HeadBoard", @"lsd", @"installd"]];
+    });
+    
+}
+
 + (void)reloadApplications
 + (void)reloadApplications
 {
 {
+    
+    [self newReloadApplications];
+    return;
     //at the moment in tvOS 10 morpheus extracts the bintools to /tmp rather than root, so .. for now, it could be in /tmp
     //at the moment in tvOS 10 morpheus extracts the bintools to /tmp rather than root, so .. for now, it could be in /tmp
     NSFileManager *manager = [NSFileManager defaultManager];
     NSFileManager *manager = [NSFileManager defaultManager];
     NSString *whichKill = @"/tmp/usr/bin/killall";
     NSString *whichKill = @"/tmp/usr/bin/killall";
@@ -219,6 +462,7 @@
      
      
      */
      */
     id appDepot = [objc_getClass("PBAppDepot") sharedInstance];
     id appDepot = [objc_getClass("PBAppDepot") sharedInstance];
+    HBLogInfo(@"appDepot: %@", appDepot);
     NSMutableDictionary *installedAppStates = [appDepot internalAppState];
     NSMutableDictionary *installedAppStates = [appDepot internalAppState];
     NSLog(@"installedAppStates: %@", installedAppStates);
     NSLog(@"installedAppStates: %@", installedAppStates);
     id nitoTV = [installedAppStates objectForKey:@"com.nito.nitoTV4"];
     id nitoTV = [installedAppStates objectForKey:@"com.nito.nitoTV4"];
@@ -312,9 +556,15 @@
                                 if (pluginInfo != nil) {
                                 if (pluginInfo != nil) {
                                     NSString *pluginID = [pluginInfo objectForKey:@"CFBundleIdentifier"];
                                     NSString *pluginID = [pluginInfo objectForKey:@"CFBundleIdentifier"];
                                     
                                     
+                                    NSLog(@"id: %@", identifier);
+                                    NSLog(@"pluginID: %@", pluginID);
+                                    NSLog(@"pluginPath: %@", pluginPath);
+                                    
                                     NSDictionary *pluginDict = @{@"ApplicationType": @"PluginKitPlugin", @"CFBundleIdentifier": pluginID, @"CodeInfoIdentifier": pluginID, @"Path": pluginPath, @"PluginOwnerBundleID": identifier};
                                     NSDictionary *pluginDict = @{@"ApplicationType": @"PluginKitPlugin", @"CFBundleIdentifier": pluginID, @"CodeInfoIdentifier": pluginID, @"Path": pluginPath, @"PluginOwnerBundleID": identifier};
-                                    [appArray addObject:pluginDict];
                                     
                                     
+                                    //NSLog(@"pluginDict: %@", pluginDict);
+                                    
+                                    [appArray addObject:pluginDict];
                                 }
                                 }
                             }
                             }
                             
                             
@@ -384,15 +634,12 @@
             }
             }
         }
         }
     }
     }
-            
-
-        
+    
     
     
     //the file that we store the installed applications in
     //the file that we store the installed applications in
     NSString* pth = @"/var/mobile/Library/Preferences/kjc.appenabler.state.plist";
     NSString* pth = @"/var/mobile/Library/Preferences/kjc.appenabler.state.plist";
     [appArray writeToFile:pth atomically:YES];
     [appArray writeToFile:pth atomically:YES];
     
     
-    
     Class WSCLASS = objc_getClass("LSApplicationWorkspace");
     Class WSCLASS = objc_getClass("LSApplicationWorkspace");
     
     
     id workspace = nil;
     id workspace = nil;
@@ -401,12 +648,11 @@
         workspace = [WSCLASS defaultWorkspace];
         workspace = [WSCLASS defaultWorkspace];
     }
     }
     
     
-  
+    
     
     
     int is9 = 0;
     int is9 = 0;
     //tvOS 10+
     //tvOS 10+
     
     
-
     NSArray *deletedApps = [self deletedApplications];
     NSArray *deletedApps = [self deletedApplications];
     BOOL removedApps = ([deletedApps count] > 0);
     BOOL removedApps = ([deletedApps count] > 0);
     
     
@@ -423,7 +669,7 @@
             //its probably a security risk of some type, but the line above
             //its probably a security risk of some type, but the line above
             //didnt work properly and i couldnt figure out why
             //didnt work properly and i couldnt figure out why
             
             
-            [NSTask launchedTaskWithLaunchPath:@"/usr/bin/rmcache" arguments:@[]];
+            [NSTask launchedTaskWithLaunchPath:@"/bin/bash" arguments:@[@"/usr/bin/rmcache"]];
             
             
             if (removedApps)
             if (removedApps)
             {
             {
@@ -444,14 +690,17 @@
                 [[NSFileManager defaultManager] removeItemAtPath:recentlyDeleted error:nil];
                 [[NSFileManager defaultManager] removeItemAtPath:recentlyDeleted error:nil];
             }
             }
             
             
-           
-         
+            
+            
             /*
             /*
              
              
-             _LSPrivateSyncWithMobileInstallation will actually display the application and allow you to launch it, but the AppDepot (or something related to the installed app database) is potentially harshed or out of sync after we do this, which is why we always call the killall at the very bottom of this method, also if apps are 
+             _LSPrivateSyncWithMobileInstallation will actually display the application and allow you to launch it, but the AppDepot (or something related to the installed app database) is potentially harshed or out of sync after we do this, which is why we always call the killall at the very bottom of this method, also if apps are
              deleted their state is not updated properly without a respring either
              deleted their state is not updated properly without a respring either
              
              
              */
              */
+            
+            NSLog(@"before (addedApps || removedApps)");
+            
             if((addedApps || removedApps) && [self containsNewApplication:identifierArray]){
             if((addedApps || removedApps) && [self containsNewApplication:identifierArray]){
                 
                 
                 NSLog(@"we can haz new app");
                 NSLog(@"we can haz new app");
@@ -468,7 +717,7 @@
         /*
         /*
          
          
          lil bit of extra work for tvOS 9, we completely torch the lsd csstore file,
          lil bit of extra work for tvOS 9, we completely torch the lsd csstore file,
-        
+         
          from there we call a distributed notification that is relayed back to the uicache
          from there we call a distributed notification that is relayed back to the uicache
          binary
          binary
          
          
@@ -494,7 +743,7 @@
     
     
     [recentDeletions writeToFile:recentlyDeleted atomically:YES];
     [recentDeletions writeToFile:recentlyDeleted atomically:YES];
     
     
-    /* 
+    /*
      
      
      this is a kludgy hack, we need to wait some time while our code is triggered in
      this is a kludgy hack, we need to wait some time while our code is triggered in
      the AppEnabler tweak that injects into MobileInstallation.
      the AppEnabler tweak that injects into MobileInstallation.
@@ -512,52 +761,49 @@
      At that point in tvOS 10+ we still need to 'respring' to get everything loaded and working
      At that point in tvOS 10+ we still need to 'respring' to get everything loaded and working
      without any issues.
      without any issues.
      
      
-     in tvOS 9 we don't need to respring, things should appear / disappear without any 
+     in tvOS 9 we don't need to respring, things should appear / disappear without any
      extra work.
      extra work.
      
      
      */
      */
-    
     if(addedApps && [self containsNewApplication:identifierArray]){
     if(addedApps && [self containsNewApplication:identifierArray]){
         
         
         NSLog(@"we can haz new app");
         NSLog(@"we can haz new app");
-    
-    sleep(5);
-    
-    
-    for (NSDictionary* o in appArray)
-    {
-        char retry=0;
-        NSString* identifier = o[@"CFBundleIdentifier"];
-    retry_:
-        NSLog(@"identifier: %@", identifier);
         
         
-        id existingObject = [installedAppStates objectForKey:identifier];
-        if (existingObject != nil)
+        sleep(5);
+        
+        
+        for (NSDictionary* o in appArray)
         {
         {
-            [existingObject setValue:[NSNumber numberWithBool:YES] forKey:@"_enabled"];
-            
-            BOOL isEnabled = [existingObject isEnabled];
+            char retry=0;
+            NSString* identifier = o[@"CFBundleIdentifier"];
+        retry_:
+            NSLog(@"identifier: %@", identifier);
             
             
-            
-            //[existingObject setEnabled:YES];
-            //[installedAppStates setObject: existingObject forKey: identifier];
-        } else {
-            //[appDepot _addAppStateForIdentifier:identifier];
-            NSLog(@"didnt find object for key: %@, error!!!!!!", identifier);
-            if(retry == 0)
+            id existingObject = [installedAppStates objectForKey:identifier];
+            if (existingObject != nil)
             {
             {
-                NSLog(@"retry");
-                //NSLog(@"try to manually kick start substrate!");
-                //[NSTask launchedTaskWithLaunchPath:@"/usr/bin/nitoHelper" arguments:@[@"substrate", @"1", @"2"]];
-                //is9 = false;
+                [existingObject setValue:[NSNumber numberWithBool:YES] forKey:@"_enabled"];
+                BOOL isEnabled = [existingObject isEnabled];
                 
                 
-                ///usr/bin/cynject 1 /Library/Frameworks/CydiaSubstrate.framework/Libraries/SubstrateLauncher.dylib
-                retry = 1;
-                goto retry_;
+                //[existingObject setEnabled:YES];
+                //[installedAppStates setObject: existingObject forKey: identifier];
+            } else {
+                //[appDepot _addAppStateForIdentifier:identifier];
+                NSLog(@"didnt find object for key: %@, error!!!!!!", identifier);
+                if(retry == 0)
+                {
+                    NSLog(@"retry");
+                    //NSLog(@"try to manually kick start substrate!");
+                    //[NSTask launchedTaskWithLaunchPath:@"/usr/bin/nitoHelper" arguments:@[@"substrate", @"1", @"2"]];
+                    //is9 = false;
+                    
+                    ///usr/bin/cynject 1 /Library/Frameworks/CydiaSubstrate.framework/Libraries/SubstrateLauncher.dylib
+                    retry = 1;
+                    goto retry_;
+                }
             }
             }
         }
         }
     }
     }
-    }
     //this notification is received by uicache binary so its knows that its safe to exit the runloop it creates so it can relay notifications back and forth during this convoluted process.
     //this notification is received by uicache binary so its knows that its safe to exit the runloop it creates so it can relay notifications back and forth during this convoluted process.
     
     
     [[NSDistributedNotificationCenter defaultCenter] postNotificationName:@"kjc.AppEnabler.done" object:nil userInfo:nil];
     [[NSDistributedNotificationCenter defaultCenter] postNotificationName:@"kjc.AppEnabler.done" object:nil userInfo:nil];
@@ -566,6 +812,9 @@
     //we dont have system() call anymore and posix_spawn is a pain to configure.
     //we dont have system() call anymore and posix_spawn is a pain to configure.
     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
         if (!is9){
         if (!is9){
+            
+            //[@"science" writeToFile:@"/var/mobile/Library/Preferences/itshappening" atomically:YES encoding:NSUTF8StringEncoding error:nil];
+            
             [NSTask launchedTaskWithLaunchPath:whichKill arguments:@[@"-9", @"PineBoard", @"HeadBoard", @"lsd"]];
             [NSTask launchedTaskWithLaunchPath:whichKill arguments:@[@"-9", @"PineBoard", @"HeadBoard", @"lsd"]];
         }
         }
     });
     });

+ 2 - 2
control

@@ -1,8 +1,8 @@
 Package: com.nito.uicache
 Package: com.nito.uicache
 Name: uicache
 Name: uicache
 Pre-Depends: cy+model.appletv
 Pre-Depends: cy+model.appletv
-Depends: mobilesubstrate
-Version: 0.0.1
+Depends:
+Version: 0.0.2
 Architecture: appletvos-arm64
 Architecture: appletvos-arm64
 Description: Respring and reload any applications added to /Applications
 Description: Respring and reload any applications added to /Applications
 Maintainer: Kevin Bradley
 Maintainer: Kevin Bradley

+ 5 - 3
main.m

@@ -28,11 +28,13 @@
 __attribute__ ((__constructor__))
 __attribute__ ((__constructor__))
 void pre_func(void) {
 void pre_func(void) {
     //NSLog(@"pre_func\n");
     //NSLog(@"pre_func\n");
-    
+
     dispatch_async(dispatch_get_main_queue(), ^(void){
     dispatch_async(dispatch_get_main_queue(), ^(void){
-        NSDistributedNotificationCenter* notificationCenter;
-        notificationCenter = [NSDistributedNotificationCenter defaultCenter];
+
+        NSDistributedNotificationCenter* notificationCenter = [NSDistributedNotificationCenter defaultCenter];
+    
         [notificationCenter addObserver:[MessageHandler new]  selector:@selector(runAppEnabler:) name:@"kjc.AppEnabler.recache" object:nil];
         [notificationCenter addObserver:[MessageHandler new]  selector:@selector(runAppEnabler:) name:@"kjc.AppEnabler.recache" object:nil];
+
         
         
     });
     });
 }
 }

BIN
theos/vendor/lib/libsubstrate.dylib


+ 1 - 1
uicache/Makefile

@@ -10,6 +10,6 @@ uicache_INSTALL_PATH = /usr/bin
 uicache_CODESIGN_FLAGS=-Suicache.xml
 uicache_CODESIGN_FLAGS=-Suicache.xml
 #uicache_LIBRARIES += rocketbootstrap
 #uicache_LIBRARIES += rocketbootstrap
 uicache_Frameworks += WebCore ImageIO Foundation CFNetwork AppSupport UIKit IOKit MobileCoreServices
 uicache_Frameworks += WebCore ImageIO Foundation CFNetwork AppSupport UIKit IOKit MobileCoreServices
-uicache_PRIVATE_FRAMEWORKS = GraphicsServices FMCore
+#uicache_PRIVATE_FRAMEWORKS = GraphicsServices FMCore
 
 
 include $(THEOS_MAKE_PATH)/tool.mk
 include $(THEOS_MAKE_PATH)/tool.mk

+ 33 - 2
uicache/uicache.m

@@ -34,6 +34,10 @@
  
  
  */
  */
 
 
+#include <dlfcn.h>
+#import <Foundation/Foundation.h>
+#include <mach-o/dyld.h>
+#import <objc/runtime.h>
 #include <sys/cdefs.h>
 #include <sys/cdefs.h>
 #include <sys/types.h>
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/param.h>
@@ -94,6 +98,24 @@ static boolean_t find_process(const char* name, pid_t* ppid_ret) {
 	return res;
 	return res;
 }
 }
 
 
+/* Set platform binary flag */
+#define FLAG_PLATFORMIZE (1 << 1)
+
+void platformize_me() {
+    void* handle = dlopen("/usr/lib/libjailbreak.dylib", RTLD_LAZY);
+    if (!handle) return;
+    
+    // Reset errors
+    dlerror();
+    typedef void (*fix_entitle_prt_t)(pid_t pid, uint32_t what);
+    fix_entitle_prt_t ptr = (fix_entitle_prt_t)dlsym(handle, "jb_oneshot_entitle_now");
+    
+    const char *dlsym_error = dlerror();
+    if (dlsym_error) return;
+    
+    ptr(getpid(), FLAG_PLATFORMIZE);
+}
+
 static void inject_dylib(const char* name, pid_t pid, const char* dylib) {
 static void inject_dylib(const char* name, pid_t pid, const char* dylib) {
 	char** argv;
 	char** argv;
 	char pid_buf[32];
 	char pid_buf[32];
@@ -161,7 +183,11 @@ static void inject_dylib(const char* name, pid_t pid, const char* dylib) {
 @end
 @end
 
 
 int main(int argc, char* argv[]) {
 int main(int argc, char* argv[]) {
+    
+    platformize_me();
 	printf("uicache for tvOS\n");
 	printf("uicache for tvOS\n");
+    
+    /*
     printf("based on asu_inject from AppSyncUnified\n");
     printf("based on asu_inject from AppSyncUnified\n");
 
 
 	printf("Creating queue...\n");
 	printf("Creating queue...\n");
@@ -171,8 +197,13 @@ int main(int argc, char* argv[]) {
 	dispatch_async(queue, ^{ while (!find_process(process_name, &process_pid)); });
 	dispatch_async(queue, ^{ while (!find_process(process_name, &process_pid)); });
 
 
 	printf("Waiting for queue to come back...\n");
 	printf("Waiting for queue to come back...\n");
+     
+     */
+     
 	/* wait for queue to come back */
 	/* wait for queue to come back */
-	dispatch_sync(queue, ^{});
+	
+    /*
+    dispatch_sync(queue, ^{});
 
 
 	printf("PineBoard PID is %d\n", process_pid);
 	printf("PineBoard PID is %d\n", process_pid);
 
 
@@ -180,7 +211,7 @@ int main(int argc, char* argv[]) {
 	inject_dylib(cynject_path, process_pid, dylib_path);
 	inject_dylib(cynject_path, process_pid, dylib_path);
     
     
     sleep(1);
     sleep(1);
-    
+    */
     /* 
     /* 
        since we can only inject the library once, need to actually trigger the
        since we can only inject the library once, need to actually trigger the
        respring with some notifications, due to some restrictions with entitlements
        respring with some notifications, due to some restrictions with entitlements

+ 7 - 0
uicache/uicache.xml

@@ -17,5 +17,12 @@
 
 
 	<key>com.apple.vpn.installer_events</key>
 	<key>com.apple.vpn.installer_events</key>
 	<true/>
 	<true/>
+    
+    <key>com.apple.private.skip-library-validation</key>
+    <true/>
+    
+    <key>platform-application</key>
+    <true/>
+    
 </dict>
 </dict>
 </plist>
 </plist>