710 lines
21 KiB
Objective-C
710 lines
21 KiB
Objective-C
//
|
|
// ZZHUtils.m
|
|
// HD wallpaper
|
|
//
|
|
// Created by aaa on 2024/7/16.
|
|
//
|
|
|
|
#import "ZZHUtils.h"
|
|
#include <sys/sysctl.h>
|
|
#include <mach/mach_time.h>
|
|
#import <UIKit/UIKit.h>
|
|
#import <WebKit/WebKit.h>
|
|
#import <sys/utsname.h>
|
|
#import <AudioToolbox/AudioToolbox.h>
|
|
#import <AVFoundation/AVFoundation.h>
|
|
#import <SystemConfiguration/SystemConfiguration.h>
|
|
#import <SystemConfiguration/CaptiveNetwork.h>
|
|
#import <netinet/in.h>
|
|
|
|
#import <UIKit/UIKit.h>
|
|
#import <sys/stat.h>
|
|
#import <AdSupport/AdSupport.h>
|
|
#import <CoreBluetooth/CoreBluetooth.h>
|
|
|
|
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
|
|
#import <CoreTelephony/CTCarrier.h>
|
|
#include <mach/mach_host.h>
|
|
#include <sys/mount.h>
|
|
|
|
|
|
#include <sys/socket.h>
|
|
#include <net/if.h>
|
|
#include <net/if_dl.h>
|
|
#import "ifaddrs.h"
|
|
#import <arpa/inet.h>
|
|
#import <Network/Network.h>
|
|
|
|
#import "resolv.h"
|
|
|
|
@implementation ZZHUtils
|
|
+ (long long)collectKernelBootTimeMillis {
|
|
struct timeval bootTime;
|
|
int mib[2] = {CTL_KERN,KERN_BOOTTIME};
|
|
size_t size = sizeof(bootTime);
|
|
if (sysctl(mib, 2, &bootTime, &size, NULL, 0) != -1) {
|
|
return bootTime.tv_sec * 1000;///秒
|
|
};
|
|
return 0;
|
|
|
|
}
|
|
|
|
+ (long long)collectMonotonicRawClockTimeMillis {
|
|
struct timespec tp;
|
|
if(clock_gettime(CLOCK_MONOTONIC_RAW, &tp) != -1) {
|
|
long xx = tp.tv_sec*1000 + tp.tv_nsec/1000000;
|
|
return xx;
|
|
}
|
|
return 0;
|
|
|
|
}
|
|
|
|
+ (unsigned long long)collectAccessibilityFeatures {
|
|
NSInteger features = 0;
|
|
if (UIAccessibilityIsClosedCaptioningEnabled()) {
|
|
features |= 0x2;
|
|
}
|
|
if (UIAccessibilityIsMonoAudioEnabled()) {
|
|
features |= 0x4;
|
|
}
|
|
if (UIAccessibilityIsReduceMotionEnabled()) {
|
|
features |= 0x8;
|
|
}
|
|
|
|
if (UIAccessibilityIsGuidedAccessEnabled()) {
|
|
features |= 0x10;
|
|
}
|
|
|
|
if (UIAccessibilityIsInvertColorsEnabled()) {
|
|
features |= 0x20;
|
|
}
|
|
|
|
if (UIAccessibilityIsVoiceOverRunning()) {
|
|
features |= 0x40;
|
|
}
|
|
|
|
if (UIAccessibilityDarkerSystemColorsEnabled()) {
|
|
features |= 0x80;
|
|
}
|
|
|
|
if (UIAccessibilityIsBoldTextEnabled()) {
|
|
features |= 0x100;
|
|
}
|
|
|
|
if (UIAccessibilityIsGrayscaleEnabled()) {
|
|
features |= 0x200;
|
|
}
|
|
|
|
if (UIAccessibilityIsReduceTransparencyEnabled()) {
|
|
features |= 0x400;
|
|
}
|
|
|
|
if (UIAccessibilityIsSpeakScreenEnabled()) {
|
|
features |= 0x800;
|
|
}
|
|
|
|
if (UIAccessibilityIsSpeakSelectionEnabled()) {
|
|
features |= 0x1000;
|
|
}
|
|
|
|
if (UIAccessibilityIsSwitchControlRunning()) {
|
|
features |= 0x2000;
|
|
}
|
|
|
|
if (UIAccessibilityIsShakeToUndoEnabled()) {
|
|
features |= 0x4000;
|
|
}
|
|
|
|
if (UIAccessibilityIsAssistiveTouchRunning()) {
|
|
features |= 0x8000;
|
|
}
|
|
|
|
if (UIAccessibilityHearingDevicePairedEar() != 0) {
|
|
features |= 0x400000;
|
|
}
|
|
|
|
if (@available(iOS 13.0, *)) {
|
|
if ([UITraitCollection currentTraitCollection].userInterfaceStyle == UIUserInterfaceStyleDark) {
|
|
features |= 0x10000;
|
|
}
|
|
|
|
if (UIAccessibilityIsOnOffSwitchLabelsEnabled()) {
|
|
features |= 0x20000;
|
|
}
|
|
|
|
if (UIAccessibilityIsVideoAutoplayEnabled()) {
|
|
features |= 0x40000;
|
|
}
|
|
|
|
if (UIAccessibilityShouldDifferentiateWithoutColor()) {
|
|
features |= 0x80000;
|
|
}
|
|
|
|
if (@available(iOS 14.0, *)) {
|
|
if (UIAccessibilityPrefersCrossFadeTransitions()) {
|
|
features |= 0x100000;
|
|
}
|
|
|
|
if (UIAccessibilityButtonShapesEnabled()) {
|
|
features |= 0x200000;
|
|
}
|
|
|
|
}
|
|
}
|
|
NSLog(@"features:\n%ld",features);
|
|
|
|
return features;
|
|
}
|
|
|
|
+ (NSString *)collectDeviceKeyboards{
|
|
NSArray *lanagues = [NSLocale preferredLanguages];
|
|
__block NSString *str = @"";
|
|
[lanagues enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
|
|
if (idx < lanagues.count-1) {
|
|
str = [str stringByAppendingFormat:@"%@,",obj];
|
|
}
|
|
else {
|
|
str = [str stringByAppendingFormat:@"%@",obj];
|
|
}
|
|
}];
|
|
return str;
|
|
}
|
|
|
|
+ (void)userAgent {
|
|
static WKWebView *webView = nil;
|
|
static dispatch_once_t onceToken;
|
|
dispatch_once(&onceToken, ^{
|
|
webView = [WKWebView new];
|
|
});
|
|
[webView evaluateJavaScript:@"function getAgent() {return navigator.userAgent;} getAgent(); " completionHandler:^(id _Nullable result, NSError * _Nullable error) {
|
|
NSLog(@"zzh the useragent:%@ ",result);
|
|
}];
|
|
|
|
// NSString *geoStr = @"if (\"geolocation\" in navigator) { navigator.geolocation.getCurrentPosition(function(position) { console.log(\"Latitude is :\", position.coords.latitude);console.log(\"Longitude is :\", position.coords.longitude);}, function(error) {console.error(\"Error Code = \" + error.code + \" - \" + error.message);});";
|
|
//
|
|
// [webView evaluateJavaScript:geoStr completionHandler:^(id _Nullable result, NSError * _Nullable error) {
|
|
// NSLog(@"zzh the geo err:%@ ",error);
|
|
// }];
|
|
}
|
|
|
|
+ (BOOL)isReachableViaWWAN {
|
|
SCNetworkReachabilityFlags flags;
|
|
struct sockaddr_in zeroAddress;
|
|
bzero(&zeroAddress, sizeof(zeroAddress));
|
|
zeroAddress.sin_len = sizeof(zeroAddress);
|
|
zeroAddress.sin_family = AF_INET;
|
|
|
|
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress);
|
|
|
|
if (SCNetworkReachabilityGetFlags(reachability, &flags)) {
|
|
if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN) {
|
|
return YES;
|
|
}
|
|
}
|
|
|
|
return NO;
|
|
}
|
|
|
|
+ (BOOL)isReachableViaWiFi {
|
|
SCNetworkReachabilityFlags flags;
|
|
BOOL result = NO;
|
|
|
|
struct sockaddr_in zeroAddress;
|
|
bzero(&zeroAddress, sizeof(zeroAddress));
|
|
zeroAddress.sin_len = sizeof(zeroAddress);
|
|
zeroAddress.sin_family = AF_INET;
|
|
|
|
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress);
|
|
|
|
if (SCNetworkReachabilityGetFlags(reachability, &flags)) {
|
|
BOOL isReachable = (flags & kSCNetworkReachabilityFlagsReachable) != 0;
|
|
BOOL needsConnection = (flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0;
|
|
BOOL isWiFi = (flags & kSCNetworkReachabilityFlagsIsWWAN) == 0;
|
|
|
|
result = isReachable && !needsConnection && isWiFi;
|
|
}
|
|
NSLog(@"result:%d",result);
|
|
return result;
|
|
}
|
|
|
|
|
|
+(BOOL)isReachable {
|
|
// 获取 SCNetworkReachabilityRef 对象
|
|
// 注意:这里直接从内存地址获取的方式在实际开发中是不安全的,
|
|
// 应该通过正确的途径获取该对象,例如使用 SCNetworkReachabilityCreateWithAddress 或 SCNetworkReachabilityCreateWithName
|
|
struct sockaddr_in zeroAddress;
|
|
bzero(&zeroAddress, sizeof(zeroAddress));
|
|
zeroAddress.sin_len = sizeof(zeroAddress);
|
|
zeroAddress.sin_family = AF_INET;
|
|
|
|
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress);
|
|
|
|
// 获取网络状态标志
|
|
SCNetworkReachabilityFlags flags;
|
|
BOOL success = SCNetworkReachabilityGetFlags(reachability, &flags);
|
|
if (!success) {
|
|
return NO;
|
|
}
|
|
|
|
// 判断网络是否可达,并调用 ALReachability 的方法
|
|
return [ZZHUtils isReachableWithFlags:flags];
|
|
}
|
|
|
|
+ (int)isReachableWithFlags:(int)arg2 {
|
|
int result = 5;
|
|
|
|
if ((result & ~arg2) != 0) {
|
|
result = (result != 0) ? 1 : 5;
|
|
}
|
|
|
|
return result & ((arg2 & 2) >> 1);
|
|
}
|
|
|
|
|
|
+ (id)collectTimeZoneOffset {
|
|
NSTimeZone *tz = [NSTimeZone localTimeZone];
|
|
NSInteger sec = [tz secondsFromGMT];
|
|
double hoursFromGMT = (double)sec / 3600.0;
|
|
return @(hoursFromGMT);
|
|
}
|
|
|
|
//获取电池数据
|
|
+ (NSDictionary *)collectBatteryInfoIfNeeded {
|
|
NSMutableDictionary *dictionary = [NSMutableDictionary new];
|
|
UIDevice *device = [UIDevice currentDevice];
|
|
BOOL originalBatteryMonitoringEnabled = device.isBatteryMonitoringEnabled;
|
|
|
|
[device setBatteryMonitoringEnabled:YES];
|
|
|
|
UIDeviceBatteryState batteryState = device.batteryState;
|
|
NSNumber *batteryStateNumber = [NSNumber numberWithInteger:batteryState];
|
|
[dictionary setObject:batteryStateNumber forKey:@"ict"];
|
|
|
|
float batteryLevel = device.batteryLevel;
|
|
int batteryPercentage = (int)(batteryLevel * 100);
|
|
if (batteryPercentage > 0) {
|
|
batteryPercentage = batteryPercentage ^ 0x10101010;
|
|
NSNumber *batteryLevelNumber = @(batteryPercentage);
|
|
[dictionary setObject:batteryLevelNumber forKey:@"icm"];
|
|
}
|
|
else {
|
|
[dictionary setObject:@"-1" forKey:@"icm"];
|
|
}
|
|
|
|
[device setBatteryMonitoringEnabled:originalBatteryMonitoringEnabled];
|
|
return dictionary;
|
|
}
|
|
|
|
+ (NSString *)collectModelRevision {
|
|
struct utsname systemInfo;
|
|
if (uname(&systemInfo) == 0) {
|
|
NSString *modelString = [NSString stringWithUTF8String:systemInfo.machine];
|
|
return modelString;
|
|
}
|
|
return nil;
|
|
}
|
|
|
|
+ (CGFloat)getScreenBrightness {
|
|
return [UIScreen mainScreen].brightness;
|
|
}
|
|
|
|
+ (CBManagerState)bluetoothState {
|
|
CBCentralManager *manager = [[CBCentralManager alloc] init];
|
|
return manager.state;
|
|
}
|
|
|
|
//设备型号
|
|
+ (NSDictionary *)collectModel {
|
|
NSMutableDictionary *arg2 = [NSMutableDictionary new];
|
|
UIDevice *device = [UIDevice currentDevice];
|
|
NSString *model = [device model];
|
|
[arg2 setObject:model forKeyedSubscript:@"model"];
|
|
return arg2;
|
|
}
|
|
|
|
+ (NSString *)collectSubplatform {
|
|
if (@available(iOS 14.0, *)) {
|
|
if ([[NSProcessInfo processInfo] isiOSAppOnMac]) {
|
|
return @"ios_on_mac";
|
|
}
|
|
}
|
|
|
|
if (@available(iOS 13.0, *)) {
|
|
if ([[NSProcessInfo processInfo] isMacCatalystApp]) {
|
|
return @"mac_catalyst";
|
|
}
|
|
}
|
|
|
|
return @"ios";
|
|
}
|
|
|
|
|
|
+ (id)collectOrientationLock {
|
|
// [[[[UIApplication sharedApplication] windows].firstObject windowScene] interfaceOrientation]
|
|
return nil;
|
|
}
|
|
|
|
+ (NSMutableDictionary *)collectScreenDimensions{
|
|
NSMutableDictionary *dict = [NSMutableDictionary new];
|
|
UIScreen *mainScreen = [UIScreen mainScreen];
|
|
CGRect bounds = [mainScreen bounds];
|
|
CGRect nativeBounds = [mainScreen nativeBounds];
|
|
CGFloat scale = [mainScreen scale];
|
|
|
|
[dict setObject:@(bounds.size.width) forKeyedSubscript:@"dx"];
|
|
[dict setObject:@(bounds.size.height) forKeyedSubscript:@"dy"];
|
|
[dict setObject:@(nativeBounds.size.width) forKeyedSubscript:@"ndx"];
|
|
[dict setObject:@(nativeBounds.size.height) forKeyedSubscript:@"ndy"];
|
|
[dict setObject:@(scale) forKeyedSubscript:@"scale"];
|
|
|
|
return dict;
|
|
}
|
|
|
|
+ (NSString *)systemVersion {
|
|
UIDevice *device = [UIDevice currentDevice];
|
|
NSString *version = [device systemVersion];
|
|
return version;
|
|
}
|
|
|
|
+ (NSMutableDictionary *)collectLocale{
|
|
|
|
NSMutableDictionary *arg2 = [NSMutableDictionary new];
|
|
NSLocale *currentLocale = [NSLocale currentLocale];
|
|
NSString *localeIdentifier = [currentLocale localeIdentifier];
|
|
[arg2 setObject:localeIdentifier forKeyedSubscript:@"locale"];
|
|
|
|
return arg2;
|
|
}
|
|
|
|
+ (NSNumber *)volume {
|
|
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
|
|
float outputVolume = [audioSession outputVolume];
|
|
NSNumber *volumeNumber = [NSNumber numberWithFloat:outputVolume];
|
|
return volumeNumber;
|
|
}
|
|
|
|
+ (void)appInfoFromBundle {
|
|
NSBundle *bundle = [NSBundle mainBundle];
|
|
|
|
NSArray *arr = [NSBundle allBundles];
|
|
NSArray *frameworks = [NSBundle allFrameworks];
|
|
NSURL *appStoreReceiptURL = [bundle appStoreReceiptURL];
|
|
NSLog(@"the bundle:%@",bundle);
|
|
}
|
|
|
|
+ (BOOL)isVPNConnected {
|
|
CFDictionaryRef proxySettings = CFNetworkCopySystemProxySettings();
|
|
if (proxySettings == NULL) {
|
|
return NO;
|
|
}
|
|
|
|
NSDictionary *settings = (__bridge_transfer NSDictionary *)proxySettings;
|
|
NSDictionary *scoped = settings[@"__SCOPED__"];
|
|
|
|
if (!scoped) {
|
|
return NO;
|
|
}
|
|
|
|
NSArray *allKeys = [scoped allKeys];
|
|
__block BOOL rr = NO;
|
|
[allKeys enumerateObjectsUsingBlock:^(NSString * _Nonnull interface, NSUInteger idx, BOOL * _Nonnull stop) {
|
|
if ([interface containsString:@"tun"] || [interface containsString:@"ppp"]) {
|
|
rr = YES;
|
|
} else {
|
|
rr = [interface containsString:@"ipsec"];
|
|
}
|
|
}];
|
|
|
|
return rr;
|
|
}
|
|
|
|
|
|
|
|
+ (SystemSoundID)muteSoundID {
|
|
SystemSoundID _muteSoundID = 0;
|
|
NSURL *soundURL = [[NSBundle mainBundle] URLForResource:@"mute" withExtension:@"aiff"];
|
|
if (soundURL) {
|
|
OSStatus status = AudioServicesCreateSystemSoundID((__bridge CFURLRef)soundURL, &_muteSoundID);
|
|
if (status == noErr) {
|
|
// 设置声音为静音
|
|
UInt32 yes = 1;
|
|
AudioServicesSetProperty(kAudioServicesPropertyIsUISound,
|
|
sizeof(_muteSoundID),
|
|
&_muteSoundID,
|
|
sizeof(yes),
|
|
&yes);
|
|
}
|
|
}
|
|
return _muteSoundID;
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (NSString *)getIDFA {
|
|
if ([[ASIdentifierManager sharedManager] isAdvertisingTrackingEnabled]) {
|
|
NSString *idfa = [[ASIdentifierManager sharedManager].advertisingIdentifier UUIDString];
|
|
return idfa;
|
|
} else {
|
|
return @"";
|
|
}
|
|
}
|
|
|
|
+ (NSString *)getIDFV {
|
|
NSString *idfv = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
|
|
return idfv;
|
|
}
|
|
|
|
|
|
#pragma mark - 获取网络运营商
|
|
+ (NSString *)getCarrierName{
|
|
CTTelephonyNetworkInfo *telephonyInfo = [[CTTelephonyNetworkInfo alloc] init];
|
|
CTCarrier *carrier = [telephonyInfo subscriberCellularProvider];
|
|
NSString *currentCountry=[carrier carrierName];
|
|
return currentCountry;
|
|
}
|
|
|
|
|
|
|
|
|
|
#pragma mark - 获取当前可用内存
|
|
|
|
/**
|
|
获取当前可用内存
|
|
|
|
@return 当前可用内存大小
|
|
*/
|
|
+(long long)getAvailableMemorySize
|
|
{
|
|
vm_statistics_data_t vmStats;
|
|
mach_msg_type_number_t infoCount = HOST_VM_INFO_COUNT;
|
|
kern_return_t kernReturn = host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vmStats, &infoCount);
|
|
if (kernReturn != KERN_SUCCESS)
|
|
{
|
|
return NSNotFound;
|
|
}
|
|
return ((vm_page_size * vmStats.free_count + vm_page_size * vmStats.inactive_count));
|
|
}
|
|
|
|
|
|
#pragma mark - 获取磁盘容量
|
|
|
|
/**
|
|
获取磁盘容量
|
|
|
|
@return 磁盘容量
|
|
*/
|
|
+(long long)getTotalDiskSize{
|
|
struct statfs buf;
|
|
unsigned long long freeSpace = -1;
|
|
if (statfs("/var", &buf) >= 0)
|
|
{
|
|
freeSpace = (unsigned long long)(buf.f_bsize * buf.f_blocks);
|
|
}
|
|
return freeSpace;
|
|
}
|
|
|
|
#pragma mark - 获取可用磁盘容量
|
|
|
|
/**
|
|
获取可用磁盘容量
|
|
|
|
@return 可用磁盘容量
|
|
*/
|
|
+(long long)getAvailableDiskSize{
|
|
struct statfs buf;
|
|
unsigned long long freeSpace = -1;
|
|
if (statfs("/var", &buf) >= 0)
|
|
{
|
|
freeSpace = (unsigned long long)(buf.f_bsize * buf.f_bavail);
|
|
}
|
|
return freeSpace;
|
|
}
|
|
|
|
/// 获取本机DNS服务器
|
|
/// libresolv.tbd需要添加这个库
|
|
+ (NSArray *)outPutDNSServers {
|
|
res_state res = malloc( sizeof(struct __res_state) );
|
|
NSMutableArray *dnsArray = [NSMutableArray new];
|
|
if (res_ninit(res) == 0) {
|
|
for (int i = 0; i < res->nscount; i++ ) {
|
|
NSString *s = [NSString stringWithUTF8String:inet_ntoa(res->nsaddr_list[i].sin_addr)];
|
|
[dnsArray addObject:s];
|
|
}
|
|
}
|
|
res_ndestroy(res);//!!改了这里
|
|
free(res);
|
|
return dnsArray.mutableCopy;
|
|
}
|
|
|
|
//是否有刘海屏
|
|
+ (BOOL)hasNotch {
|
|
return [UIScreen mainScreen].nativeBounds.size.height != UIScreen.mainScreen.bounds.size.height;
|
|
}
|
|
|
|
//获取系统字号
|
|
+ (NSNumber *)getSystemFontSize {
|
|
UIFont *font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
|
|
UIFontDescriptor *ctFont = font.fontDescriptor;
|
|
NSNumber *fontSize = [ctFont objectForKey:@"NSFontSizeAttribute"];
|
|
return fontSize;
|
|
}
|
|
|
|
//获取processInfo
|
|
+ (NSDictionary *)processInfo {
|
|
NSProcessInfo *processInfo = [NSProcessInfo processInfo];
|
|
return processInfo.environment;
|
|
}
|
|
|
|
|
|
#define IOS_CELLULAR @"pdp_ip0"//有些分配的地址为en0 有些分配的en1
|
|
#define IOS_WIFI2 @"en2"
|
|
#define IOS_WIFI1 @"en1"
|
|
#define IOS_WIFI @"en0"//
|
|
#define IOS_VPN @"utun0" vpn很少用到可以注释
|
|
#define IP_ADDR_IPv4 @"ipv4"
|
|
#define IP_ADDR_IPv6 @"ipv6"
|
|
|
|
//获取所有相关IP信息
|
|
+ (NSDictionary *)getIPAddresses{
|
|
NSMutableDictionary *addresses = [NSMutableDictionary dictionaryWithCapacity:8];
|
|
|
|
// retrieve the current interfaces - returns 0 on success
|
|
struct ifaddrs *interfaces;
|
|
if(!getifaddrs(&interfaces)) {
|
|
// Loop through linked list of interfaces
|
|
struct ifaddrs *interface;
|
|
for(interface=interfaces; interface; interface=interface->ifa_next) {
|
|
if(!(interface->ifa_flags & IFF_UP) /* || (interface->ifa_flags & IFF_LOOPBACK) */ ) {
|
|
continue; // deeply nested code harder to read
|
|
}
|
|
const struct sockaddr_in *addr = (const struct sockaddr_in*)interface->ifa_addr;
|
|
char addrBuf[ MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) ];
|
|
if(addr && (addr->sin_family==AF_INET || addr->sin_family==AF_INET6)) {
|
|
NSString *name = [NSString stringWithUTF8String:interface->ifa_name];
|
|
NSString *type;
|
|
if(addr->sin_family == AF_INET) {
|
|
if(inet_ntop(AF_INET, &addr->sin_addr, addrBuf, INET_ADDRSTRLEN)) {
|
|
type = IP_ADDR_IPv4;
|
|
}
|
|
} else {
|
|
const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*)interface->ifa_addr;
|
|
if(inet_ntop(AF_INET6, &addr6->sin6_addr, addrBuf, INET6_ADDRSTRLEN)) {
|
|
type = IP_ADDR_IPv6;
|
|
}
|
|
}
|
|
if(type) {
|
|
NSString *key = [NSString stringWithFormat:@"%@/%@", name, type];
|
|
addresses[key] = [NSString stringWithUTF8String:addrBuf];
|
|
}
|
|
}
|
|
}
|
|
// Free memory
|
|
freeifaddrs(interfaces);
|
|
}
|
|
return [addresses count] ? addresses : nil;
|
|
}
|
|
|
|
#warning -----暂时还未去成功获取
|
|
+ (NSDictionary *)wifiInfo {
|
|
NSArray *ifs = (__bridge_transfer id)CNCopySupportedInterfaces();
|
|
NSLog(@"interfaces:%@",ifs);
|
|
NSDictionary *info = nil;
|
|
for (NSString *ifname in ifs) {
|
|
info = (__bridge_transfer NSDictionary *)CNCopyCurrentNetworkInfo((__bridge CFStringRef)ifname);
|
|
NSLog(@"wifiInfo %@ => %@",ifname,info);
|
|
}
|
|
return info;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#warning -----暂时还未去处理的伪代码
|
|
//- (NSDictionary *)collectAdServerInfo {
|
|
// NSMutableDictionary *result = [NSMutableDictionary dictionary];
|
|
//
|
|
// // Server Cache
|
|
// [result setObject:[self.sdk stringForKey:[ALSetting serverCache]] forKeyedSubscript:@"sc"];
|
|
//
|
|
// // Server Cache 2
|
|
// [result setObject:[self.sdk stringForKey:[ALSetting serverCache2]] forKeyedSubscript:@"sc2"];
|
|
//
|
|
// // Server Cache 3
|
|
// [result setObject:[self.sdk stringForKey:[ALSetting serverCache3]] forKeyedSubscript:@"sc3"];
|
|
//
|
|
// // Server Installed At
|
|
// [result setObject:[self.sdk stringForKey:[ALSetting serverInstalledAt]] forKeyedSubscript:@"server_installed_at"];
|
|
//
|
|
// // Server Installed At V2
|
|
// [result setObject:[self.sdk stringForKey:[ALSetting serverInstalledAtV2]] forKeyedSubscript:@"server_installed_at_v2"];
|
|
//
|
|
// // Persisted Data
|
|
// NSString *persistedData = [[self.sdk userDefaults] stringForKey:[ALUserDefaultsKey persistedData]];
|
|
// [result al_setStringValueIfValid:persistedData forKey:@"persisted_data"];
|
|
//
|
|
// return [result copy];
|
|
//}
|
|
|
|
#warning ----还未检测到该方法的调用...
|
|
+ (NSString *)collectCurrentRadioAccessTechnologyIfNeeded{
|
|
return @"";
|
|
}
|
|
|
|
|
|
#pragma mark ----检测是否越狱
|
|
|
|
+ (BOOL)isJailbroken {
|
|
if ([self checkCommonJailbreakFiles] || [self checkSuspiciousApps] || [self canWriteToSystemDirectories]) {
|
|
return YES;
|
|
}
|
|
|
|
return NO;
|
|
}
|
|
|
|
+ (BOOL)checkCommonJailbreakFiles {
|
|
NSArray *jailbreakFiles = @[
|
|
@"/Applications/Cydia.app",
|
|
@"/Library/MobileSubstrate/MobileSubstrate.dylib",
|
|
@"/bin/bash",
|
|
@"/usr/sbin/sshd",
|
|
@"/etc/apt",
|
|
@"/private/var/lib/apt/"
|
|
];
|
|
|
|
for (NSString *path in jailbreakFiles) {
|
|
if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
|
|
return YES;
|
|
}
|
|
}
|
|
|
|
return NO;
|
|
}
|
|
|
|
+ (BOOL)checkSuspiciousApps {
|
|
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"cydia://package/com.example.package"]]) {
|
|
return YES;
|
|
}
|
|
|
|
return NO;
|
|
}
|
|
|
|
+ (BOOL)canWriteToSystemDirectories {
|
|
NSError *error;
|
|
NSString *stringToWrite = @"Jailbreak Test";
|
|
NSString *filePath = @"/private/jailbreakTest.txt";
|
|
|
|
[stringToWrite writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:&error];
|
|
|
|
if (error == nil) {
|
|
[[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];
|
|
return YES;
|
|
}
|
|
|
|
return NO;
|
|
}
|
|
|
|
|
|
@end
|