Skip to content

Commit 16f6615

Browse files
committed
Profiles tab rework, now App Expiry tab, update idevice
1 parent e9d9f35 commit 16f6615

7 files changed

Lines changed: 1188 additions & 151 deletions

File tree

StikJIT/Views/MainTabView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ struct MainTabView: View {
5757
TabDescriptor(id: "deviceinfo", title: "Device Info", systemImage: "iphone.and.arrow.forward") { AnyView(DeviceInfoView()) }
5858
]
5959
if FeatureFlags.showBetaTabs {
60-
tabs.append(TabDescriptor(id: "profiles", title: "Profiles", systemImage: "magazine.fill") { AnyView(ProfileView()) })
60+
tabs.append(TabDescriptor(id: "profiles", title: "App Expiry", systemImage: "calendar.badge.clock") { AnyView(ProfileView()) })
6161
tabs.append(TabDescriptor(id: "processes", title: "Processes", systemImage: "rectangle.stack.person.crop") { AnyView(ProcessInspectorView()) })
6262
tabs.append(TabDescriptor(id: "devicelibrary", title: "Devices", systemImage: "list.bullet.rectangle") { AnyView(DeviceLibraryView()) })
6363
if FeatureFlags.isLocationSpoofingEnabled {

StikJIT/Views/ProfileView.swift

Lines changed: 418 additions & 139 deletions
Large diffs are not rendered by default.

StikJIT/Views/SettingsView.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,8 @@ struct SettingsView: View {
9191
TabOption(id: "scripts", title: "Scripts", detail: "Manage automation scripts", icon: "scroll", isBeta: false)
9292
]
9393
options.append(TabOption(id: "deviceinfo", title: "Device Info", detail: "View detailed device metadata", icon: "iphone.and.arrow.forward", isBeta: false))
94-
if FeatureFlags.showBetaTabs {
95-
options.append(TabOption(id: "profiles", title: "Profiles", detail: "Install/remove profiles", icon: "magazine", isBeta: true))
96-
}
94+
options.append(TabOption(id: "profiles", title: "App Expiry", detail: "Check app expiration date, install/remove profiles", icon: "calendar.badge.clock", isBeta: false))
95+
9796
if FeatureFlags.showBetaTabs {
9897
options.append(TabOption(id: "processes", title: "Processes", detail: "Inspect running apps", icon: "rectangle.stack.person.crop", isBeta: true))
9998
options.append(TabOption(id: "devicelibrary", title: "Devices", detail: "Manage external devices", icon: "list.bullet.rectangle", isBeta: true))

StikJIT/idevice/JITEnableContext.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ typedef void (^SyslogErrorHandler)(NSError *error);
6767
- (NSDictionary<NSString*, NSString*>*)getAppListWithError:(NSError**)error;
6868
- (NSDictionary<NSString*, NSString*>*)getAllAppsWithError:(NSError**)error;
6969
- (NSDictionary<NSString*, NSString*>*)getHiddenSystemAppsWithError:(NSError**)error;
70+
- (NSArray<NSDictionary*>*)getSideloadedAppsWithError:(NSError**)error;
7071
@end
7172

7273
@interface JITEnableContext(Syslog)

StikJIT/idevice/applist.m

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,65 @@ static BOOL isHiddenSystemApp(plist_t app)
149149
return result;
150150
}
151151

152+
static NSArray<NSDictionary*>* getSideloadedApps(IdeviceProviderHandle *provider,
153+
NSString **error) {
154+
InstallationProxyClientHandle *client = NULL;
155+
IdeviceFfiError* err = installation_proxy_connect(provider, &client);
156+
if (err) {
157+
*error = [NSString stringWithFormat:@"Failed to connect to installation proxy: %s", err->message];
158+
idevice_error_free(err);
159+
return nil;
160+
}
161+
162+
plist_t *apps = NULL;
163+
size_t count = 0;
164+
err = installation_proxy_get_apps(client, NULL, NULL, 0, (void*)&apps, &count);
165+
if (err) {
166+
*error = [NSString stringWithFormat:@"Failed to get apps: %s", err->message];
167+
idevice_error_free(err);
168+
installation_proxy_client_free(client);
169+
return nil;
170+
}
171+
172+
NSMutableArray<NSDictionary*>* result = [NSMutableArray new];
173+
174+
for (size_t i = 0; i < count; i++) {
175+
plist_t app = ((plist_t *)apps)[i];
176+
177+
plist_t profileValidatedNode = 0;
178+
if(!(profileValidatedNode = plist_dict_get_item(app, "ProfileValidated"))) {
179+
continue;
180+
}
181+
182+
char* bin = 0;
183+
uint32_t size = 0;
184+
plist_to_bin(app, &bin, &size);
185+
if(!bin || size == 0) {
186+
continue;
187+
}
188+
189+
NSData* d = [NSData dataWithBytes:bin length:size];
190+
NSError* err;
191+
NSDictionary* dict = [NSPropertyListSerialization propertyListWithData:d options:0 format:nil error:&err];
192+
plist_mem_free(bin);
193+
194+
if(err) {
195+
continue;
196+
}
197+
198+
[result addObject:dict];
199+
200+
}
201+
202+
installation_proxy_client_free(client);
203+
for(int i = 0; i < count; ++i) {
204+
plist_free(apps[i]);
205+
}
206+
idevice_data_free((uint8_t *)apps, sizeof(plist_t)*count);
207+
208+
return result;
209+
}
210+
152211
static NSDictionary<NSString*, NSString*> *performAppQuery(IdeviceProviderHandle *provider,
153212
BOOL requireGetTaskAllow,
154213
NSString **error,
@@ -265,6 +324,21 @@ @implementation JITEnableContext(App)
265324
return apps;
266325
}
267326

327+
- (NSArray<NSDictionary*>*)getSideloadedAppsWithError:(NSError**)error {
328+
[self ensureHeartbeatWithError:error];
329+
if(*error) {
330+
return nil;
331+
}
332+
333+
NSString* errorStr = nil;
334+
NSArray<NSDictionary*>* apps = getSideloadedApps(provider, &errorStr);
335+
if (errorStr) {
336+
*error = [self errorWithStr:errorStr code:-17];
337+
return nil;
338+
}
339+
return apps;
340+
}
341+
268342
- (UIImage*)getAppIconWithBundleId:(NSString*)bundleId error:(NSError**)error {
269343
[self ensureHeartbeatWithError:error];
270344
if(*error) {

0 commit comments

Comments
 (0)