//
//  XSHackIos.m
//  nochange
//
//  Created by mac on 2024/10/15.
//

#import <Foundation/Foundation.h>
#import <sqlite3.h>
#include <ftw.h>
#include <spawn.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#import <objc/runtime.h>
#include <dlfcn.h>
#include <SpringBoard/SBWindow.h>

#import "XSHelper.h"
#import "XSHackIos.h"
#import "XSPhoneConfig.h"
#import "XSPhoneInfo.h"
/**
获取当前应用
 */
SBApplication* XSGetFrontMostApplication(void)
{
    //TODO: might cause problem here. Both _accessibilityFrontMostApplication failed or front most application springboard will cause app be nil.
    __block id app = nil;
    NSLog(@"XS- getFrontMostApplication");
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    dispatch_sync(dispatch_get_main_queue(), ^{
        @try{
            
            SpringBoard *springboard = (SpringBoard *)[UIApplication sharedApplication];
            //SpringBoard *springboard = (SpringBoard*)[%c(SpringBoard) sharedApplication];
            if ([springboard respondsToSelector:@selector(_accessibilityFrontMostApplication)]) {
                app = [springboard performSelector:@selector(_accessibilityFrontMostApplication)];
                NSLog(@"XS- Simulated home button press, %@", app);
            }
            // app = [springboard _accessibilityFrontMostApplication];
            //NSLog(@"com.zjx.springboard: app: %@, id: %@", app, [app displayIdentifier]);
             
        }
        @catch (NSException *exception) {
            NSLog(@"XS-: Debug: %@", exception.reason);
        }
        dispatch_semaphore_signal(semaphore);
        });
    // 设置超时时间为5秒
    dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC);

    // 等待信号量，最多等待5秒
    long result = dispatch_semaphore_wait(semaphore, timeout);

    if (result == 0) {
        // 在超时之前收到了信号
        NSLog(@"XSGetFrontMostApplication end");
    } else {
        // 超时
        NSLog(@"XSGetFrontMostApplication 等待超时");
    }
     
    return app;
}


NSString* XSFrontMostAppId(void) {
    SBApplication* sbapp = XSGetFrontMostApplication();
    if (sbapp == nil || [sbapp isEqual:[NSNull null]]) {
        return @"";
    }
    return sbapp.bundleIdentifier;
}


extern char **environ;
//执行系统命令
int XSRuncmd(char *args[])
{
    printf("XSRuncmd: args ");
    for (int i = 0; args[i] != NULL; i++) {
        printf("%s ", args[i]);
    }
    printf("\n");
    
    posix_spawnattr_t attr;
    posix_spawn_file_actions_t fact;
    pid_t pid;
    
    posix_spawnattr_init(&attr);
    posix_spawn_file_actions_init(&fact);
    posix_spawn(&pid,args[0], NULL, NULL,args,environ);
    perror("posix_spawn");
    NSLog(@"XS- pid=%d,child pid = %d\n",getpid(),pid);
    int stat=0;
    waitpid(pid,&stat,0);
    NSLog(@"XS- stat is %d\n",stat);
    return pid;
}

int unlink_cb(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf){
    int rv = remove(fpath);
    if (rv)
        perror(fpath);
    
    return rv;
}

void XSSystem(const char *cmd) {
    int stat = nftw(cmd, unlink_cb, 64, FTW_DEPTH | FTW_PHYS);
    NSLog(@"nftw res: %d", stat);
}


NSString* XSGetAppExecutable(NSString *pkgName) {
    
    //获取应用程序列表
    Class cls = NSClassFromString(@"LSApplicationWorkspace");
    
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
    id s = [(id)cls performSelector:NSSelectorFromString(@"defaultWorkspace")];
    NSArray *array = [s performSelector:NSSelectorFromString(@"allApplications")];
#pragma clang diagnostic pop
    
    Class LSApplicationProxy_class = NSClassFromString(@"LSApplicationProxy");
    
    for (LSApplicationProxy_class in array) {
        
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
        NSString *res = [LSApplicationProxy_class performSelector:@selector(applicationIdentifier)];
        //NSString *strBundleID = [LSApplicationProxy_class performSelector:@selector(bundleIdentifier)];
#pragma clang diagnostic pop
        // localizedName
        
        if ([res isEqualToString:pkgName]) {
            NSURL * bundleFullURL = [LSApplicationProxy_class performSelector:@selector(bundleURL)];
            NSString * s_bundleURL = [bundleFullURL absoluteString];
            
            NSString *prefix = @"file://";
            NSRange needleRange = NSMakeRange(prefix.length,
                                              s_bundleURL.length - prefix.length );
            NSString *needle = [s_bundleURL substringWithRange:needleRange];
            NSBundle *bundle = [NSBundle bundleWithPath:needle];
            NSString* executable = [[bundle infoDictionary] valueForKeyPath:@"CFBundleExecutable"];
            return executable;
            
        }
        
    }
    return nil;
}

int XSReboot(void) {
    char *argv[] = {
        "/usr/sbin/reboot",
        NULL
    };
    int r = XSRuncmd(argv);
   
    return r;
}

int XSKillApp(NSString *appexe) {
    if(appexe) {
        const char* app = [appexe UTF8String];
        char *appStr = strdup(app);
        char *argv[] = {
            "/usr/bin/killall",
            "-9",
            appStr,
            NULL
        };
        int r = XSRuncmd(argv);
        free(appStr);
        return r;
    }
    return 0;
}

int kill2(NSString *appexe) {
    NSString *cmd = [NSString stringWithFormat:@"/usr/bin/killall -9 %@", appexe];
    const char* app = [cmd UTF8String];
    char *appStr = strdup(app);
    int r = system2(appStr, NULL, NULL);
    free(appStr);
    return r;
}


int XSKillAppByName(NSString *pkgName){
    NSString* appexe = XSGetAppExecutable(pkgName);
    return kill2(appexe);
}


int (*_XSOpenApp)(CFStringRef, Boolean);

int XSBringAppForeground(NSString *appIdentifier)
{
    void* sbServices = dlopen("/System/Library/PrivateFrameworks/SpringBoardServices.framework/SpringBoardServices", RTLD_LAZY);
    CFStringRef appBundleName = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@"), appIdentifier);
    //[NSString stringWithFormat:@"%s", eventData];
    NSLog(@"XS-: Switch to application: %@", appBundleName);
    if (!_XSOpenApp) {
        _XSOpenApp = (int(*)(CFStringRef, Boolean))dlsym(sbServices,"SBSLaunchApplicationWithIdentifier");
    }
    return _XSOpenApp(appBundleName, false);
}

void bringAppToForeground(NSString *bundleID) {
    @autoreleasepool {
        Class FBSSystemServiceClass = NSClassFromString(@"FBSSystemService");
        if (FBSSystemServiceClass) {
            id service = [FBSSystemServiceClass sharedService];
            NSDictionary *options = @{
                @"BSLaunchOrigin": @"SpringBoard",
                @"BSSuspended": @NO,
            };
            
            [service openApplication:bundleID
                           options:options
                       clientPort:0
                       withResult:^(NSError *error) {
                if (error) {
                    NSLog(@"Failed to bring app to foreground: %@", error);
                }
            }];
        }
    }
}

void activateApp(NSString *bundleID){
    // 这个方法不行
    Class SBApplicationControllerClass = NSClassFromString(@"SBApplicationController");
    if (SBApplicationControllerClass) {
        id controller = [SBApplicationControllerClass sharedInstance];
        id app = [controller applicationWithBundleIdentifier:bundleID];
        if ([app respondsToSelector:@selector(activate)]) {
            [app activate];
        }
    }
}



void XSRemoteUnlock(void) {
    // 获取 SBLockScreenManager 的共享实例
    
    // 获取 SBUIController 实例
    @autoreleasepool {
        Class sbUIControllerClass = objc_getClass("SBUIController");
        id sbUIController = [sbUIControllerClass performSelector:@selector(sharedInstance)];
        
        // 检查设备是否在锁屏状态
        if ([sbUIController respondsToSelector:@selector(isOnLockScreen)]) {
            BOOL isLocked = [sbUIController performSelector:@selector(isOnLockScreen)];
            
            if (isLocked) {
                // 模拟滑动解锁（对于没有密码的设备）
                CGPoint startPoint = CGPointMake(50, CGRectGetMidY([UIScreen mainScreen].bounds));
                CGPoint endPoint = CGPointMake(CGRectGetMaxX([UIScreen mainScreen].bounds) - 50, CGRectGetMidY([UIScreen mainScreen].bounds));
                
                UITouch *touch = [[UITouch alloc] init];
                [touch setValue:[NSValue valueWithCGPoint:startPoint] forKey:@"_locationInWindow"];
                
                UIEvent *event = [[UIEvent alloc] init];
                [event setValue:@(UIEventTypeTouches) forKey:@"_type"];
                [event setValue:[NSSet setWithObject:touch] forKey:@"_touches"];
                
                [[UIApplication sharedApplication] sendEvent:event];
                
                [touch setValue:[NSValue valueWithCGPoint:endPoint] forKey:@"_locationInWindow"];
                [[UIApplication sharedApplication] sendEvent:event];
                
                // 对于有密码的设备，还需要模拟输入密码
                // 这部分代码会更复杂，需要模拟点击数字键盘
                
                NSLog(@"Simulated unlock gesture");
            } else {
                NSLog(@"Device is not locked");
            }
        } else {
            NSLog(@"Unable to determine lock state");
        }
        
        // 模拟按下 Home 键
        SpringBoard *springboard = (SpringBoard *)[UIApplication sharedApplication];
        if ([springboard respondsToSelector:@selector(_simulateHomeButtonPress)]) {
            [springboard performSelector:@selector(_simulateHomeButtonPress)];
            NSLog(@"Simulated home button press");
        }
    }
        
    /*
    Class lockScreenManagerClass = objc_getClass("SBLockScreenManager");
    if (lockScreenManagerClass) {
        id lockScreenManager = [lockScreenManagerClass performSelector:@selector(sharedInstance)];
        // 获取 SBUserAgent 的共享实例
        Class userAgentClass = objc_getClass("SBUserAgent");
        id userAgent = [userAgentClass performSelector:@selector(sharedUserAgent)];
        
        if (lockScreenManager && userAgent) {
            
            // 调用解锁方法
            if ([lockScreenManager performSelector:@selector(isUILocked)]) {
                [lockScreenManager performSelector:@selector(unlockUIFromSource:withOptions:)
                                        withObject:@(1)
                                        withObject:nil];
                
                // 尝试唤醒屏幕
                [userAgent performSelector:@selector(undimScreen)];
                        
                // 尝试解锁设备
                [userAgent performSelector:@selector(unlockDevice)];
                
                NSLog(@"-ad -log- Unlock command sent");
            }else {
                NSLog(@"-ad log- No lock");
            }
        } else {
            NSLog(@"Unable to get LockScreenManager");
        }
    } else {
        NSLog(@"-ad log- NO SBLockScreenManager");
    }
     */
}

NSString* getDeviceName(void)
{
    struct utsname systemInfo;
    uname(&systemInfo);

    return [NSString stringWithCString:systemInfo.machine
                                encoding:NSUTF8StringEncoding];
}
/*
round up number by multiple of another number
*/
int roundUp(int numToRound, int multiple)
{
    if (multiple == 0)
        return numToRound;

    int remainder = numToRound % multiple;
    if (remainder == 0)
        return numToRound;

    return numToRound + multiple - remainder;
}

CGImageRef createScreenShotCGImageRef(void)
{
    Boolean isiPad8orUp = false;

    CGFloat scale = [UIScreen mainScreen].scale;
    CGSize screenSize = [UIScreen mainScreen].bounds.size;

    int height = (int)(screenSize.height * scale);
    int width = (int)(screenSize.width * scale);

    // check whether it is ipad8 or later
    NSString *searchText = getDeviceName();

    NSRange range = [searchText rangeOfString:@"^iPad[8-9]|iPad[1-9][0-9]+" options:NSRegularExpressionSearch];
    if (range.location != NSNotFound) { // ipad pro (3rd) or later
        isiPad8orUp = true;
    }

    if (isiPad8orUp)
    {
        if (width < height)
        {
            int temp = width;
            width = height;
            height = temp;
        }
    }
    else
    {
        if (width > height)
        {
            int temp = width;
            width = height;
            height = temp;
        }
    }

    int bytesPerElement = 4;
    int bytesPerRow = roundUp(bytesPerElement * width, 32);

    NSNumber *IOSurfaceBytesPerElement = [NSNumber numberWithInteger:bytesPerElement];
    NSNumber *IOSurfaceBytesPerRow = [NSNumber numberWithInteger:bytesPerRow]; // don't know why but it should be a multiple of 32
    NSNumber *IOSurfaceAllocSize = [NSNumber numberWithInteger:bytesPerRow * height];
    NSNumber *nheight = [NSNumber numberWithInteger:height];
    NSNumber *nwidth = [NSNumber numberWithInteger:width];
    NSNumber *IOSurfacePixelFormat = [NSNumber numberWithInteger:1111970369];
    NSNumber *IOSurfaceIsGlobal = [NSNumber numberWithInteger:1];

    NSDictionary *properties = [[NSDictionary alloc] initWithObjectsAndKeys:IOSurfaceAllocSize, @"IOSurfaceAllocSize"
                                , IOSurfaceBytesPerElement, @"IOSurfaceBytesPerElement", IOSurfaceBytesPerRow, @"IOSurfaceBytesPerRow", nheight, @"IOSurfaceHeight",
                                IOSurfaceIsGlobal, @"IOSurfaceIsGlobal", IOSurfacePixelFormat, @"IOSurfacePixelFormat", nwidth, @"IOSurfaceWidth", nil];

    IOSurfaceRef screenSurface = IOSurfaceCreate((__bridge CFDictionaryRef)(properties));

    properties = nil;
    
    IOSurfaceLock(screenSurface, 0, NULL);
    CARenderServerRenderDisplay(0, CFSTR("LCD"), screenSurface, 0, 0);
        
    CGImageRef cgImageRef = nil;
    if (screenSurface) {
        cgImageRef = UICreateCGImageFromIOSurface(screenSurface);
        int targetWidth = CGImageGetWidth(cgImageRef);
        int targetHeight = CGImageGetHeight(cgImageRef);

        if (isiPad8orUp) // rotate 90 degrees counterclockwise
        {
            CGColorSpaceRef colorSpaceInfo = CGImageGetColorSpace(cgImageRef);
            CGContextRef bitmap;

            //if (sourceImage.imageOrientation == UIImageOrientationUp || sourceImage.imageOrientation == UIImageOrientationDown) {
                bitmap = CGBitmapContextCreate(NULL, targetHeight, targetWidth, CGImageGetBitsPerComponent(cgImageRef), CGImageGetBytesPerRow(cgImageRef), colorSpaceInfo, kCGImageAlphaPremultipliedFirst);
            //} else {
                //bitmap = CGBitmapContextCreate(NULL, targetHeight, targetWidth, CGImageGetBitsPerComponent(cgImageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);

            //}

            CGFloat degrees = -90.f;
            CGFloat radians = degrees * (M_PI / 180.f);

            CGContextTranslateCTM (bitmap, 0.5*targetHeight, 0.5*targetWidth);
            CGContextRotateCTM (bitmap, radians);
            CGContextTranslateCTM (bitmap, -0.5*targetWidth, -0.5*targetHeight);

            CGContextDrawImage(bitmap, CGRectMake(0, 0, targetWidth, targetHeight), cgImageRef);
            
            CGImageRelease(cgImageRef);
            cgImageRef = CGBitmapContextCreateImage(bitmap);

            CGColorSpaceRelease(colorSpaceInfo);
            CGContextRelease(bitmap);
        }
    }
    IOSurfaceUnlock(screenSurface, 0, NULL);
    CFRelease(screenSurface);
    screenSurface = nil;

    return cgImageRef;
}

UIImage* XSCcaptureScreen2(void) {
    CGImageRef cgImage = createScreenShotCGImageRef();
    UIImage *uiImage = [UIImage imageWithCGImage:cgImage];
    NSLog(@"img2:%@", uiImage);
    CFRelease(cgImage);
    return uiImage;
}


UIImage* XSCaptureScreen(void) {
    NSLog(@"captureScreen");
    UIImage* res =  _UICreateScreenUIImage();
    NSLog(@"img1:%@", res);
    if (res && res != nil && ![res isEqual:[NSNull null]]) {
        return res;
    }
    return XSCcaptureScreen2();
}

UIImage* defaultIconWithSize (CGSize size, NSString *appName) {
    UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    // 使用随机颜色填充矩形
    CGFloat hue = (CGFloat)arc4random() / UINT32_MAX;
    UIColor *color = [UIColor colorWithHue:hue saturation:0.5 brightness:0.8 alpha:1.0];
    CGContextSetFillColorWithColor(context, color.CGColor);
    CGContextFillRect(context, CGRectMake(0, 0, size.width, size.height));
    
    // 可选：添加应用名称的首字母
    NSString *initial = [[appName substringToIndex:1] uppercaseString];
    UIColor *textColor = [UIColor whiteColor];
    NSDictionary *attributes = @{
        NSFontAttributeName: [UIFont boldSystemFontOfSize:size.width * 0.6],
        NSForegroundColorAttributeName: textColor
    };
    CGSize textSize = [initial sizeWithAttributes:attributes];
    CGPoint textPoint = CGPointMake((size.width - textSize.width) / 2,
                                    (size.height - textSize.height) / 2);
    [initial drawAtPoint:textPoint withAttributes:attributes];
    
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return image;
}

NSArray* XSGetApps(void){
    
    NSMutableArray *appInfoArray = [NSMutableArray array];
    //获取应用程序列表
    Class cls = NSClassFromString(@"LSApplicationWorkspace");
    id s = [(id)cls performSelector:NSSelectorFromString(@"defaultWorkspace")];
    NSArray *array = [s performSelector:NSSelectorFromString(@"allApplications")];
    Class LSApplicationProxy_class = NSClassFromString(@"LSApplicationProxy");
    
    for (LSApplicationProxy_class in array){
        
        NSString * applicationIdentifier = [LSApplicationProxy_class performSelector:@selector(applicationIdentifier)];
        
        NSString *strBundleID = [LSApplicationProxy_class performSelector:@selector(bundleIdentifier)];
        NSString *localizedName = [LSApplicationProxy_class performSelector:@selector(localizedName)];
        // localizedName
        //获取应用的相关信息
        NSString *strVersion =  [LSApplicationProxy_class performSelector:@selector(bundleVersion)];
        NSString *strShortVersion =  [LSApplicationProxy_class performSelector:@selector(shortVersionString)];
        NSURL * bundleFullURL = [LSApplicationProxy_class performSelector:@selector(bundleURL)];
        NSString * s_bundleURL = [bundleFullURL absoluteString];
        
        NSURL *strContainerURL = [LSApplicationProxy_class performSelector:@selector(containerURL)];
        NSString *strContainerDataPath = [strContainerURL path];
        
        if ([s_bundleURL hasPrefix:@"file:///private/"]){
            
            
            NSString *prefix = @"file://";
            NSRange needleRange = NSMakeRange(prefix.length,
                                              s_bundleURL.length - prefix.length );
            
            NSString *needle = [s_bundleURL substringWithRange:needleRange];
            
            NSBundle *bundle = [NSBundle bundleWithPath:needle];
            
            NSString* executable = [[bundle infoDictionary] valueForKeyPath:@"CFBundleExecutable"];
            
        }
        UIImage *icon = nil;
        
        // 方法1: 尝试从bundle中获取图标
           NSBundle *appBundle = [NSBundle bundleWithIdentifier:applicationIdentifier];
           if (appBundle) {
               NSString *iconPath = [appBundle pathForResource:@"AppIcon60x60" ofType:@"png"];
               if (iconPath) {
                   icon = [UIImage imageWithContentsOfFile:iconPath];
               }
           }
           
           // 方法2: 如果方法1失败，尝试使用UIApplication的私有API
           if (!icon) {
               UIApplication *application = [UIApplication sharedApplication];
               if ([application respondsToSelector:@selector(_iconDataForBundleIdentifier:)]) {
                   NSData *iconData = [application performSelector:@selector(_iconDataForBundleIdentifier:) withObject:applicationIdentifier];
                   if (iconData) {
                       icon = [UIImage imageWithData:iconData];
                   }
               }
           }
        // 尝试使用_applicationIconImageForBundleIdentifier:获取图标
            if ([UIImage respondsToSelector:@selector(_applicationIconImageForBundleIdentifier:format:scale:)]) {
                icon = [UIImage _applicationIconImageForBundleIdentifier:applicationIdentifier format:10 scale:[UIScreen mainScreen].scale];
            }
        
        if (!icon) {
              // 使用默认图标
            icon = defaultIconWithSize(CGSizeMake(60, 60), localizedName);
          }

        NSString *logInfo = [NSString stringWithFormat:@"bundleId:%@,name:%@,containerPath:%@,version:%@,shortVersion:%@,icon:%@", strBundleID, localizedName, strContainerDataPath, strVersion, strShortVersion, icon];
        NSLog(@"%@", logInfo);
        NSDictionary *dic = @{
            @"bundleId": applicationIdentifier ?: @"",
            @"name": localizedName ?: @"",
            @"containerPath": strContainerDataPath ?: @"",
            @"version": strVersion ?: @"",
            @"shortVersion": strShortVersion ?: @"",
            @"icon": icon ?: [NSNull null]
        };
        
        
        [appInfoArray addObject:dic];
    }
    
    return [appInfoArray copy];
}



void XSCleanSafariHistory(void) {
    NSString *historyPath = @"/var/mobile/Library/Safari/History.db";
    sqlite3 *database;
    
    if (sqlite3_open([historyPath UTF8String], &database) == SQLITE_OK) {
        char *errMsg;
        const char *sql = "DELETE FROM history_items; DELETE FROM history_visits; VACUUM;";
        
        if (sqlite3_exec(database, sql, NULL, NULL, &errMsg) != SQLITE_OK) {
            NSLog(@"Error cleaning Safari history: %s", errMsg);
            sqlite3_free(errMsg);
        } else {
            NSLog(@"Safari history cleaned successfully");
        }
        sqlite3_close(database);
    } else {
        NSLog(@"Unable to open database");
    }
}



/**
 清楚safari数据
 */
void XSCleanSafari(void) {
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSError *error;
    
    // 清理 Safari 缓存
    NSString *safariCachePath = @"/var/mobile/Library/Caches/com.apple.mobilesafari";
    [XSHelper rmFiles:safariCachePath];
    
    NSString *safariSafePath = @"/var/mobile/Library/Caches/com.apple.Safari.SafeBrowsing";
    [XSHelper rmFiles:safariSafePath];
    // 清理 Safari 的 WebKit 缓存
    NSString *webKitCachePath = @"/var/mobile/Library/WebKit/com.apple.mobilesafari";
    [XSHelper rmFiles:webKitCachePath];
    
    
    // 清理 Safari 历史记录
    // cleanSafariHistory();
    /*
     NSString *historyPath = @"/var/mobile/Library/Safari/History.db";
     [fileManager removeItemAtPath:historyPath error:&error];
     if (error) {
     NSLog(@"Error clearing Safari history: %@", error.localizedDescription);
     }
     */
    NSString *historyPath = @"/var/mobile/Library/Safari";
    [XSHelper rmFiles:historyPath];
    // 清理 Safari Cookies
    NSString *cookiesPath = @"/var/mobile/Library/Cookies/Cookies.binarycookies";
    [XSHelper rmFiles:cookiesPath];
    
    NSLog(@"Safari data cleared successfully");
    
    NSFileManager *man = [NSFileManager defaultManager];
    // 清理cookie
    NSString *cookiepath = @"/var/mobile/Library/Cookies";
   
    [XSHelper rmFiles:cookiepath];
    
    cookiepath = @"/private/var/root/Library/Cookies";
    
    [XSHelper rmFiles:cookiepath];
    
    
    // 获取safari的沙盒路径
    NSString* safaricontainer = nil;
    NSString* installplist = @"/var/mobile/Library/Caches/com.apple.mobile.installation.plist";
    if ([man fileExistsAtPath:installplist]) {
        NSDictionary* plist = [NSDictionary dictionaryWithContentsOfFile:installplist];
        id obj = plist[@"User"][@"com.apple.mobilesafari"];
        if (obj == nil) {
            obj = plist[@"System"][@"com.apple.mobilesafari"];
        }
        if (obj != nil) {
            safaricontainer = obj[@"Container"];
        }
    } else {
        Class LSApplicationProxy_cls = objc_getClass("LSApplicationProxy");
        id obj = [LSApplicationProxy_cls performSelector:@selector(applicationProxyForIdentifier:) withObject:@"com.apple.mobilesafari"];
        
        if (obj != nil && [obj respondsToSelector:@selector(dataContainerURL)]) {
            safaricontainer = [[obj performSelector:@selector(dataContainerURL)] path];
        }
    }
    if(safaricontainer) {
        // 清理library
        NSString* libpath = [safaricontainer stringByAppendingPathComponent:@"Library"];
        NSString* libcachepath = [libpath stringByAppendingPathComponent:@"Caches"];
        [XSHelper rmFiles:libcachepath];
    }
     
}



void XSCleanKeychain(void) {
    NSFileManager* man = [NSFileManager defaultManager];
    if ([man fileExistsAtPath:@"/var/Keychains/keychain-2.db"]) {
        
        /*
        char *cpCmd = "/usr/bin/cp";
        if ([man fileExistsAtPath:@"/bin/cp"]) {
            cpCmd = "/bin/cp";
        }
       
        char *cmds[] = {
            cpCmd,
            "/var/Keychains/keychain-2.db",
            "/tmp/",
            NULL
        };
         */
        // XSRuncmd(cmds);
        
        XSSystem("cp /var/Keychains/keychain-2.db /tmp/");
        sqlite3* ppDb;
        char cmd[256];
        if (0 == sqlite3_open("/tmp/keychain-2.db", &ppDb)) {
            strcpy(cmd, "DELETE FROM cert WHERE agrp<>'apple' and agrp not like '%apple%' and agrp <> 'ichat' and agrp <>'lockdown-identities'");
            sqlite3_exec(ppDb, cmd, 0, 0, 0);
            strcpy(cmd, "DELETE FROM keys WHERE agrp<>'apple' and agrp not like '%apple%' and agrp <> 'ichat' and agrp <>'lockdown-identities'");
            sqlite3_exec(ppDb, cmd, 0, 0, 0);
            strcpy(cmd, "DELETE FROM inet WHERE agrp<>'apple' and agrp not like '%apple%' and agrp <> 'ichat' and agrp <>'lockdown-identities'");
            sqlite3_exec(ppDb, cmd, 0, 0, 0);
            /*
            char *cmds1[] = {
                cpCmd,
                "/tmp/keychain-2.*",
                "/var/Keychains/",
                NULL
            };
             */
            //XSRuncmd(cmds1);
            
            XSSystem("cp /tmp/keychain-2.* /var/Keychains/");
        }
        //free(cpCmd);
    }
}


void XSCleanPastboard(void) {
      UIPasteboard* pb = [UIPasteboard generalPasteboard];
    if (pb != nil) {
        NSArray* items = [pb items];
        if (items != nil) {
            items = [NSArray array];
        }
        [pb setItems:items];
    }
     
    NSFileManager* man = [NSFileManager defaultManager];
    NSProcessInfo* proc = [NSProcessInfo processInfo];
    BOOL isbe8 = FALSE;
    NSOperatingSystemVersion ver;
    ver.majorVersion = 8;
    ver.minorVersion = 0;
    ver.patchVersion = 0;
    if ([proc respondsToSelector:@selector(isOperatingSystemAtLeastVersion:)]) {
        isbe8 = [proc isOperatingSystemAtLeastVersion:ver];
    }
     
    NSString* pbplist = nil;
   
    if ([man fileExistsAtPath:@"/System/Library/LaunchDaemons/com.apple.UIKit.pasteboardd.plist"]) {
        pbplist = @"/System/Library/LaunchDaemons/com.apple.UIKit.pasteboardd.plist";
        //pbbundle = @"com.apple.UIKit.pasteboardd";
    }
    else if ([man fileExistsAtPath:@"/Library/LaunchDaemons/com.apple.UIKit.pasteboardd.plist"]) {
        pbplist = @"/Library/LaunchDaemons/com.apple.UIKit.pasteboardd.plist";
        //pbbundle = @"com.apple.UIKit.pasteboardd";
    }
    else if ([man fileExistsAtPath:@"/System/Library/LaunchDaemons/com.apple.pasteboard.pasted.plist"]) {
        pbplist = @"/System/Library/LaunchDaemons/com.apple.pasteboard.pasted.plist";
        //pbbundle = @"com.apple.pasteboard.pasted";
    }
     
    // BOOL pbdbexist = [man fileExistsAtPath:@"/var/mobile/Library/Caches/com.apple.UIKit.pboard/pasteboardDB"];
    NSString* pbcontainer = nil;
    if ([man fileExistsAtPath:@"/var/mobile/Library/Caches/com.apple.UIKit.pboard"]) {
        pbcontainer = @"/var/mobile/Library/Caches/com.apple.UIKit.pboard";
    } else if ([man fileExistsAtPath:@"/var/mobile/Library/Caches/com.apple.Pasteboard"]) {
        pbcontainer = @"/var/mobile/Library/Caches/com.apple.Pasteboard";
    }
    if (!isbe8 && [man fileExistsAtPath:pbplist]) {
        XSSystem("launchctl unload -w");
    }
    if (pbcontainer != nil && [man fileExistsAtPath:pbcontainer]) {
        NSString* cmd = [NSString stringWithFormat:@"rm -rf %@/*", pbcontainer];
        XSSystem([cmd UTF8String]);
    }
  
}



NSString* getAppExecutable(NSString *pkgName){

    //获取应用程序列表
    Class cls = NSClassFromString(@"LSApplicationWorkspace");
    id s = [(id)cls performSelector:NSSelectorFromString(@"defaultWorkspace")];
    NSArray *array = [s performSelector:NSSelectorFromString(@"allApplications")];
    Class LSApplicationProxy_class = NSClassFromString(@"LSApplicationProxy");

    for (LSApplicationProxy_class in array){

        NSString * res = [LSApplicationProxy_class performSelector:@selector(applicationIdentifier)];
        
        NSString *strBundleID = [LSApplicationProxy_class performSelector:@selector(bundleIdentifier)];
        // localizedName
     
        if ([res isEqualToString:pkgName]) {
            
        
            NSURL * bundleFullURL = [LSApplicationProxy_class performSelector:@selector(bundleURL)];
            NSString * s_bundleURL = [bundleFullURL absoluteString];
            
            if ([s_bundleURL hasPrefix:@"file:///private/"]){
                
                
                NSString *prefix = @"file://";
                NSRange needleRange = NSMakeRange(prefix.length,
                                                  s_bundleURL.length - prefix.length );
                
                NSString *needle = [s_bundleURL substringWithRange:needleRange];
                
                NSBundle *bundle = [NSBundle bundleWithPath:needle];
        
                NSString* executable = [[bundle infoDictionary] valueForKeyPath:@"CFBundleExecutable"];
                return executable;
            }}
    }

    return nil;
}



NSString* getAppSandboxPath(NSString *app){

    //获取应用程序列表
    Class cls = NSClassFromString(@"LSApplicationWorkspace");
    id s = [(id)cls performSelector:NSSelectorFromString(@"defaultWorkspace")];
    NSArray *array = [s performSelector:NSSelectorFromString(@"allApplications")];
    Class LSApplicationProxy_class = NSClassFromString(@"LSApplicationProxy");

    for (LSApplicationProxy_class in array){

        NSString *strBundleID = [LSApplicationProxy_class performSelector:@selector(bundleIdentifier)];
       
        //获取应用的相关信息
        NSString *strVersion =  [LSApplicationProxy_class performSelector:@selector(bundleVersion)];
        NSString *strShortVersion =  [LSApplicationProxy_class performSelector:@selector(shortVersionString)];

        NSURL *strContainerURL = [LSApplicationProxy_class performSelector:@selector(containerURL)];
        NSString *strContainerDataPath = [strContainerURL path];
        

        //NSLog(@"bundleID：%@ localizedName: %@", strBundleID, strLocalizedName);

        if ([strBundleID isEqualToString:app]) {
            return strContainerDataPath;
        }
    }

    return nil;
}

NSString* XSGetAppInfoPath(NSString *app) {
    NSString *appDataPath = getAppSandboxPath(app);
    if (appDataPath) {
        //判断目录，只有这两个目录才能清除，如果是其他的目录，比如/var/mobile/Documents/ 千万不能清除，
        //否则可能需要重新激活或产生其他的问题
        if ([appDataPath hasPrefix:@"/private/var/mobile/Containers/Data/Application/"] ||
            [appDataPath hasPrefix:@"/var/mobile/Containers/Data/Application/"]) {
            NSString *strLibraryPath = [appDataPath stringByAppendingPathComponent:@"Library"];
            NSString *strPreferencesPath = [strLibraryPath stringByAppendingPathComponent:@"Preferences"];
            NSString *appInfoPlist = [strPreferencesPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.plist", app]];
            NSLog(@"app info path:%@", appInfoPlist);
            return appInfoPlist;
        }
    }
    return nil;
}

NSDictionary* XSGetAppInfo(NSString *appInfoPlist) {
    if (appInfoPlist) {
        NSDictionary *appInfo = [[NSDictionary alloc] initWithContentsOfFile:appInfoPlist];
        return appInfo;
    }
    return nil;
}

void XSSaveAppInfo(NSDictionary *dic, NSString *appInfoPath) {
    NSMutableDictionary *saveDic = [[NSMutableDictionary alloc] init];
    if (dic) {
        id kzzhDeviceInfo = dic[@"kzzhDeviceInfo"];
        if (kzzhDeviceInfo) {
            [saveDic setValue:kzzhDeviceInfo forKey:@"kzzhDeviceInfo"];
        }
        
        id appInfo = dic[@"appInfo"];
        if (appInfo) {
            [saveDic setValue:appInfo forKey:@"appInfo"];
        }
        
        id applovinInfo = dic[@"applovinInfo"];
        if (applovinInfo) {
            [saveDic setValue:applovinInfo forKey:@"applovinInfo"];
        }
        id kNilOptions = dic[@"kNilOptions"];
        if (kNilOptions) {
            [saveDic setValue:kNilOptions forKey:@"kNilOptions"];
        }
        id bfaceDictKey = dic[@"bfaceDictKey"];
        XSPhoneConfig *config = [XSPhoneConfig sharedInstance];
        NSString *deviceId = config.DeviceId;
        NSString *loclIp = [[XSPhoneInfo sharedInstance] IPAddress];
        if (bfaceDictKey) {
            NSMutableDictionary *tempDic = [NSMutableDictionary dictionaryWithDictionary:bfaceDictKey];
            [tempDic setValue:deviceId forKey:@"adbrush_deviceid"];
            [tempDic setValue:loclIp forKey:@"adbrush_localip"];
            [saveDic setValue:tempDic forKey:@"bfaceDictKey"];
        } else {
            NSDictionary *tempDic = @{@"adbrush_deviceid": deviceId, @"adbrush_localip": loclIp};
            [saveDic setValue:tempDic forKey:@"bfaceDictKey"];
        }
        /*
        NSDictionary *strAttrib = [NSDictionary dictionaryWithObjectsAndKeys:
                                   @"mobile",NSFileGroupOwnerAccountName,
                                   @"mobile",NSFileOwnerAccountName,
                                   nil];
        */
        [saveDic writeToFile:appInfoPath atomically:YES];
    }
}

void cleanBundleContainer(NSString *appDataPath) {
    //判断目录，只有这两个目录才能清除，如果是其他的目录，比如/var/mobile/Documents/ 千万不能清除，
        //否则可能需要重新激活或产生其他的问题
        if ([appDataPath hasPrefix:@"/private/var/mobile/Containers/Data/Application/"] ||
            [appDataPath hasPrefix:@"/var/mobile/Containers/Data/Application/"]) {

            NSFileManager *fm = [NSFileManager defaultManager];

            NSString *strDocumentsPath = [appDataPath stringByAppendingPathComponent:@"Documents"];
            [fm removeItemAtPath:strDocumentsPath error:nil];

            NSString *strLibraryPath = [appDataPath stringByAppendingPathComponent:@"Library"];
            

            NSString *strCachesPath = [strLibraryPath stringByAppendingPathComponent:@"Caches"];
            NSString *strPreferencesPath = [strLibraryPath stringByAppendingPathComponent:@"Preferences"];
            
            
            [fm removeItemAtPath:strLibraryPath error:nil];

            NSString *strTmpPath = [appDataPath stringByAppendingPathComponent:@"tmp"];
            [fm removeItemAtPath:strTmpPath error:nil];

            NSString *strStoreKitPath = [appDataPath stringByAppendingPathComponent:@"StoreKit"];
            [fm removeItemAtPath:strStoreKitPath error:nil];

            //删除沙盒目录之后，要以mobile身份创建相应的目录，否则可能会因为权限问题使再次安装的应用
            //不能写入应用沙盒目录
            NSDictionary *strAttrib = [NSDictionary dictionaryWithObjectsAndKeys:
                                       @"mobile",NSFileGroupOwnerAccountName,
                                       @"mobile",NSFileOwnerAccountName,
                                       nil];

            [fm createDirectoryAtPath:appDataPath withIntermediateDirectories:NO
                attributes:strAttrib error:nil];
            [fm createDirectoryAtPath:strDocumentsPath withIntermediateDirectories:NO
                attributes:strAttrib error:nil];
            [fm createDirectoryAtPath:strLibraryPath withIntermediateDirectories:NO
                attributes:strAttrib error:nil];
            [fm createDirectoryAtPath:strCachesPath withIntermediateDirectories:NO
                attributes:strAttrib error:nil];
            [fm createDirectoryAtPath:strPreferencesPath withIntermediateDirectories:NO
                attributes:strAttrib error:nil];
            [fm createDirectoryAtPath:strTmpPath withIntermediateDirectories:NO
                attributes:strAttrib error:nil];
        }
}

void clearAppStringInfo(NSString* appPath) {
    NSFileManager *fm = [NSFileManager defaultManager];
    if (![fm fileExistsAtPath:appPath]) {
        return;
    }
    if ([appPath hasPrefix:@"/private/var/containers/Bundle/Application"] ||
        [appPath hasPrefix:@"/var/containers/Bundle/Application"] ||
        [appPath hasPrefix:@"/private/var/mobile/Containers/Data/Application"] ||
        [appPath hasPrefix:@"/var/mobile/Containers/Data/Application"]) {
        NSString *itunesPath = [appPath stringByDeletingLastPathComponent];
        NSLog(@"itunes path: %@", itunesPath);
        NSString *file1 = [NSString stringWithFormat:@"%@/iTunesMetadata.plist", itunesPath];
        NSString *file2 = [NSString stringWithFormat:@"%@/iTunesArtwork", itunesPath];
        NSString *file3 = [NSString stringWithFormat:@"%@/BundleMetadata.plist", itunesPath];
        [fm removeItemAtPath:file1 error:nil];
        [fm removeItemAtPath:file2 error:nil];
        [fm removeItemAtPath:file3 error:nil];
    }
}

void XSClearAppData(NSString *app) {
    NSString *appPath = getAppSandboxPath(app);
    if (appPath) {
        cleanBundleContainer(appPath);
        clearAppStringInfo(appPath);
    }
}

BOOL screenIsLocked(void) {
    Class sbUIControllerClass = objc_getClass("SBUIController");
    id sbUIController = [sbUIControllerClass performSelector:@selector(sharedInstance)];
    
    // 检查设备是否在锁屏状态
    if ([sbUIController respondsToSelector:@selector(isOnLockScreen)]) {
        BOOL isLocked = [sbUIController performSelector:@selector(isOnLockScreen)];
        return isLocked;
    }
    return YES;
}

void XSClearAll(NSString *appId) {
    XSCleanSafari();
    XSCleanKeychain();
    XSCleanPastboard();
    XSClearAppData(appId);
}


double getCPUTemperature(void) {
    double temperature = 0.0;
    
    io_service_t platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleSMC"));
    if (platformExpert) {
        CFMutableDictionaryRef propertyDict = NULL;
        kern_return_t result = IORegistryEntryCreateCFProperties(platformExpert, &propertyDict, kCFAllocatorDefault, 0);
        if (result == kIOReturnSuccess) {
            CFDataRef data = CFDictionaryGetValue(propertyDict, CFSTR("TC0P"));
            if (data) {
                const UInt8 *bytes = CFDataGetBytePtr(data);
                temperature = (double)bytes[0];
            }
            CFRelease(propertyDict);
        }
        IOObjectRelease(platformExpert);
    }
    
    return temperature;
}

// 注入网络权限
void injectNetworkPermissions(void) {
    // 创建授权选项
    SecTaskRef task = SecTaskCreateFromSelf(NULL);
    if (!task) return;
    
    CFErrorRef error = NULL;
    CFTypeRef entitled = SecTaskCopyValueForEntitlement(task,
                                                       CFSTR("com.apple.private.network.client"),
                                                       &error);
    
    if (!entitled) {
        // 添加网络客户端权限
        CFDictionaryRef entitlements = CFDictionaryCreateMutable(NULL, 0,
                                                               &kCFTypeDictionaryKeyCallBacks,
                                                               &kCFTypeDictionaryValueCallBacks);
        
        CFDictionarySetValue((CFMutableDictionaryRef)entitlements,
                           CFSTR("com.apple.private.network.client"),
                           kCFBooleanTrue);
        
        static void *security = NULL;
        static SecTaskSetEntitlementsPtr SetEntitlements = NULL;
        static dispatch_once_t onceToken;
        
        dispatch_once(&onceToken, ^{
            security = dlopen("/System/Library/Frameworks/Security.framework/Security", RTLD_LAZY);
            if (security) {
                SetEntitlements = (SecTaskSetEntitlementsPtr)dlsym(security, "SecTaskSetEntitlements");
            }
        });
        
        if (!security || !SetEntitlements) {
            NSLog(@"XS- no SecTaskSetEntitlements");
            
            return;
        }
        
        // 应用权限
        SetEntitlements(task, entitlements);
        
        CFRelease(entitlements);
    }
    
    if (entitled) CFRelease(entitled);
    CFRelease(task);
}


BOOL injectEntitlementsWithOptions(NSDictionary *options, NSError **error) {
    static void *security = NULL;
    static SecTaskSetEntitlementsPtr SetEntitlements = NULL;
    static dispatch_once_t onceToken;
    
    dispatch_once(&onceToken, ^{
        security = dlopen("/System/Library/Frameworks/Security.framework/Security", RTLD_LAZY);
        if (security) {
            SetEntitlements = (SecTaskSetEntitlementsPtr)dlsym(security, "SecTaskSetEntitlements");
        }
    });
    
    if (!security || !SetEntitlements) {
        if (error) {
            *error = [NSError errorWithDomain:@"EntitlementsInjectorErrorDomain"
                                       code:-1
                                   userInfo:@{NSLocalizedDescriptionKey: @"无法加载必要的系统函数"}];
        }
        return NO;
    }
    
    SecTaskRef task = SecTaskCreateFromSelf(NULL);
    if (!task) {
        if (error) {
            *error = [NSError errorWithDomain:@"EntitlementsInjectorErrorDomain"
                                       code:-2
                                   userInfo:@{NSLocalizedDescriptionKey: @"无法创建任务引用"}];
        }
        return NO;
    }
    
    // 转换权限字典
    NSMutableDictionary *entitlements = [NSMutableDictionary dictionary];
    
    // 基本网络权限
    entitlements[@"com.apple.developer.networking.HotspotConfiguration"] = @YES;
    entitlements[@"com.apple.developer.networking.networkextension"] = @YES;
    entitlements[@"com.apple.developer.networking.wifi-info"] = @YES;
    
    // 添加用户自定义权限
    [entitlements addEntriesFromDictionary:options];
    
    // 注入权限
    CFErrorRef cfError = NULL;
    Boolean success = SetEntitlements(task, (__bridge CFDictionaryRef)entitlements);
    
    CFRelease(task);
    
    if (!success) {
        if (error) {
            *error = (__bridge NSError *)cfError;
        }
        if (cfError) CFRelease(cfError);
        return NO;
    }
    
    return YES;
}

// 验证权限是否注入成功
BOOL verifyEntitlement(NSString *entitlementName) {
    SecTaskRef task = SecTaskCreateFromSelf(NULL);
    if (!task) return NO;
    
    CFErrorRef error = NULL;
    CFTypeRef value = SecTaskCopyValueForEntitlement(task,
                                                    (__bridge CFStringRef)entitlementName,
                                                    &error);
    
    CFRelease(task);
    
    if (error) {
        CFRelease(error);
        return NO;
    }
    
    BOOL hasEntitlement = (value != NULL);
    if (value) CFRelease(value);
    
    return hasEntitlement;
}


pid_t system2(const char * command, int * infp, int * outfp)
{
    int p_stdin[2];
    int p_stdout[2];
    pid_t pid;

    if (pipe(p_stdin) == -1)
        return -1;

    if (pipe(p_stdout) == -1) {
        close(p_stdin[0]);
        close(p_stdin[1]);
        return -1;
    }

    pid = fork();

    if (pid < 0) {
        close(p_stdin[0]);
        close(p_stdin[1]);
        close(p_stdout[0]);
        close(p_stdout[1]);
        return pid;
    } else if (pid == 0) {
        close(p_stdin[1]);
        dup2(p_stdin[0], 0);
        close(p_stdout[0]);
        dup2(p_stdout[1], 1);
        dup2(open("/dev/null", O_RDONLY), 2);
        /// Close all other descriptors for the safety sake.
        for (int i = 3; i < 4096; ++i)
            close(i);

        setsid();
        execl("/bin/sh", "sh", "-c", command, NULL);
        _exit(1);
    }

    close(p_stdin[0]);
    close(p_stdout[1]);

    if (infp == NULL) {
        close(p_stdin[1]);
    } else {
        *infp = p_stdin[1];
    }

    if (outfp == NULL) {
        close(p_stdout[0]);
    } else {
        *outfp = p_stdout[0];
    }

    if (pid > 0)
    {
        waitpid(pid, NULL, 0);
    }
    return pid;
}



void printInfo(id object) {
    if (!object) {
        NSLog(@"Object is nil");
        return;
    }
    
    // 获取类名
    NSLog(@"\nClass: %@", NSStringFromClass([object class]));
    
    // 1. 获取所有属性
    unsigned int propertyCount;
    objc_property_t *properties = class_copyPropertyList([object class], &propertyCount);
    
    NSLog(@"\n=== Properties ===");
    for (unsigned int i = 0; i < propertyCount; i++) {
        objc_property_t property = properties[i];
        
        // 属性名
        const char *propertyName = property_getName(property);
        // 属性特性
        const char *attributes = property_getAttributes(property);
        
        NSLog(@"Property: %s, Attributes: %s", propertyName, attributes);
        
        // 尝试获取属性值
        @try {
            NSString *name = [NSString stringWithUTF8String:propertyName];
            id value = [object valueForKey:name];
            NSLog(@"Value: %@", value);
        } @catch (NSException *exception) {
            NSLog(@"Cannot access value");
        }
    }
    free(properties);
    
    // 2. 获取所有实例方法
    unsigned int methodCount;
    Method *methods = class_copyMethodList([object class], &methodCount);
    
    NSLog(@"\n=== Methods ===");
    for (unsigned int i = 0; i < methodCount; i++) {
        Method method = methods[i];
        SEL selector = method_getName(method);
        NSString *methodName = NSStringFromSelector(selector);
        
        // 获取参数个数
        int arguments = method_getNumberOfArguments(method);
        struct objc_method_description *desc = method_getDescription(method);
        NSLog(@"args:%s", desc->types);
        // 获取返回值类型
        char *returnType = method_copyReturnType(method);
        
        NSLog(@"Method: %@, Args: %d, ReturnType: %s", methodName, arguments, returnType);
        free(returnType);
    }
    free(methods);
    
    // 3. 获取所有实例变量
    unsigned int ivarCount;
    Ivar *ivars = class_copyIvarList([object class], &ivarCount);
    
    NSLog(@"\n=== Instance Variables ===");
    for (unsigned int i = 0; i < ivarCount; i++) {
        Ivar ivar = ivars[i];
        const char *ivarName = ivar_getName(ivar);
        const char *ivarType = ivar_getTypeEncoding(ivar);
        
        NSLog(@"Ivar: %s, Type: %s", ivarName, ivarType);
    }
    free(ivars);
    
    // 4. 获取遵循的协议
    unsigned int protocolCount;
    Protocol * __unsafe_unretained *protocols = class_copyProtocolList([object class], &protocolCount);
    
    NSLog(@"\n=== Protocols ===");
    for (unsigned int i = 0; i < protocolCount; i++) {
        Protocol *protocol = protocols[i];
        const char *protocolName = protocol_getName(protocol);
        NSLog(@"Protocol: %s", protocolName);
    }
    free(protocols);
}

// 递归获取父类信息
void printClassHierarchy(Class cls) {
    NSLog(@"\n=== Class Hierarchy ===");
    while (cls) {
        NSLog(@"Class: %@", NSStringFromClass(cls));
        cls = class_getSuperclass(cls);
    }
}

// 获取方法的详细信息
void printMethodInfo(Method method) {
    SEL selector = method_getName(method);
    NSString *methodName = NSStringFromSelector(selector);
    
    // 获取参数类型
    unsigned int argCount = method_getNumberOfArguments(method);
    NSMutableArray *argTypes = [NSMutableArray array];
    
    for (unsigned int i = 0; i < argCount; i++) {
        char *argType = method_copyArgumentType(method, i);
        if (argType) {
            [argTypes addObject:[NSString stringWithUTF8String:argType]];
            free(argType);
        }
    }
    
    // 获取返回值类型
    char *returnType = method_copyReturnType(method);
    NSString *returnTypeString = returnType ? [NSString stringWithUTF8String:returnType] : @"?";
    free(returnType);
    
    NSLog(@"Method: %@\nReturn Type: %@\nArgument Types: %@",
          methodName, returnTypeString, argTypes);
}

// 获取属性的详细信息
void printPropertyInfo(objc_property_t property) {
    const char *name = property_getName(property);
    const char *attributes = property_getAttributes(property);
    
    unsigned int attrCount;
    objc_property_attribute_t *attrs = property_copyAttributeList(property, &attrCount);
    
    NSMutableArray *attributeDetails = [NSMutableArray array];
    for (unsigned int i = 0; i < attrCount; i++) {
        NSString *attrName = @(attrs[i].name);
        NSString *attrValue = attrs[i].value ? @(attrs[i].value) : @"";
        [attributeDetails addObject:[NSString stringWithFormat:@"%@=%@", attrName, attrValue]];
    }
    
    free(attrs);
    
    NSLog(@"Property: %s\nAttributes: %s\nDetailed Attributes: %@",
          name, attributes, attributeDetails);
}



// 属性特性解析工具
NSDictionary* parsePropertyAttributes(const char *attributes) {
    NSString *attributeString = @(attributes);
    NSArray *components = [attributeString componentsSeparatedByString:@","];
    NSMutableDictionary *result = [NSMutableDictionary dictionary];
    
    for (NSString *component in components) {
        if ([component hasPrefix:@"T"]) {
            result[@"type"] = [component substringFromIndex:1];
        } else if ([component isEqualToString:@"R"]) {
            result[@"readonly"] = @YES;
        } else if ([component isEqualToString:@"C"]) {
            result[@"copy"] = @YES;
        } else if ([component isEqualToString:@"&"]) {
            result[@"strong"] = @YES;
        } else if ([component isEqualToString:@"W"]) {
            result[@"weak"] = @YES;
        } else if ([component isEqualToString:@"N"]) {
            result[@"nonatomic"] = @YES;
        }
    }
    
    return result;
}



// 获取前台应用
void getFrontAppWindows(void) {
    SpringBoard *springBoard = (SpringBoard *)[UIApplication sharedApplication];
    UIApplication *frontApp = [springBoard _accessibilityFrontMostApplication];
    printInfo(frontApp);
    // 获取SBWindowManager类
    Class SBWindowManagerClass = NSClassFromString(@"SBWindowManager");
    id windowManager = [SBWindowManagerClass sharedInstance];
    NSLog(@"SBWindowManager");
    printInfo(windowManager);
    UIWindow *win = [[NSClassFromString(@"SBUIController") sharedInstance] window];
    printInfo(win);
    // 尝试获取windows
    if ([windowManager respondsToSelector:@selector(windows)]) {
        NSArray *windows = [windowManager windows];
        NSLog(@"windows: %@", windows);
    }
}


void findButtonsInView(UIView *view) {
    NSLog(@"findButtonsInView:%@",view);
    // 如果是按钮
    if ([view isKindOfClass:[UIButton class]]) {
        UIButton *button = (UIButton *)view;
        CGRect frameInWindow = [button convertRect:button.bounds toView:nil];
        
        NSString *title = [button titleForState:UIControlStateNormal];
        NSLog(@"Button: %@, Position: %@", title, NSStringFromCGRect(frameInWindow));
    }
    
    // 遍历子视图
    for (UIView *subview in view.subviews) {
        findButtonsInView(subview);
    }
}

UIWindow* getKeyWindow(void) {
    NSLog(@"getKeyWindow");
    getFrontAppWindows();
    UIWindow *keyWindow = nil;
    
    // iOS 13及以上版本
    if (@available(iOS 13.0, *)) {
        NSSet *connectedScenes = [[UIApplication sharedApplication] connectedScenes];
        for (UIScene *scene in connectedScenes) {
            if ([scene isKindOfClass:[UIWindowScene class]]) {
                UIWindowScene *windowScene = (UIWindowScene *)scene;
                for (UIWindow *window in windowScene.windows) {
                    NSLog(@"getKeyWindow: %@", window);
                    findButtonsInView(window);
                    if (window.isKeyWindow) {
                        keyWindow = window;
                        //break;
                    }
                }
            }
        }
    } else {
        // iOS 13以下版本
        keyWindow = [[UIApplication sharedApplication] keyWindow];
    }
    
    return keyWindow;
}


void getAllButtons(void) {
    dispatch_sync(dispatch_get_main_queue(),^{
        // 获取当前窗口
        //FBScene *scene = getForegroundAppScene();
        //findButtonsInView(scene.window);
        
        UIWindow *keyWindow = getKeyWindow();
        // 递归查找按钮
        findButtonsInView(keyWindow);
    });
}

