├── Extender_0.9.41_005.ipa ├── Extendlife.xm ├── Makefile ├── com.julioverne.extendlife_0.1_iphoneos-arm.deb ├── com.julioverne.extendlife_0.3_iphoneos-arm.deb ├── com.julioverne.extendlife_0.3a_iphoneos-arm.deb ├── com.julioverne.extendlife_0.4_iphoneos-arm.deb ├── com.julioverne.extendlife_0.5_iphoneos-arm.deb └── com.julioverne.extendlife_0.6_iphoneos-arm.deb /Extender_0.9.41_005.ipa: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/julioverne/Extendlife/dee6a826ef6ecd1e01d7d5b8e25769c649cde48c/Extender_0.9.41_005.ipa -------------------------------------------------------------------------------- /Extendlife.xm: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | #import 5 | #import 6 | #import 7 | #import 8 | #import 9 | 10 | extern const char *__progname; 11 | 12 | #undef HBLogError 13 | #define HBLogError(...) 14 | #define NSLog(...) 15 | 16 | @interface LSApplicationProxy : NSObject 17 | - (NSURL*)resourcesDirectoryURL; 18 | @end 19 | @interface InstalledController : UITableViewController 20 | - (LSApplicationProxy *)proxyAtIndexPath:(NSIndexPath *)path; 21 | @end 22 | 23 | @interface SettingsExtendfile : PSListController 24 | + (id) shared; 25 | @end 26 | 27 | @interface DocumentsExtendfile : UITableViewController 28 | { 29 | NSMutableArray *searchData; 30 | } 31 | + (id) shared; 32 | - (void)Refresh; 33 | @end 34 | 35 | const char * origTeamID; 36 | const char * myTeamID; 37 | 38 | static BOOL disableTemp = YES; 39 | 40 | size_t (*strlen_o)(const char *str); 41 | size_t strlen_r(const char *str) 42 | { 43 | 44 | if(!disableTemp &&str&&myTeamID&&origTeamID&&strcmp(str, origTeamID)==0) { 45 | memcpy((void*)str, (const void *)myTeamID, 10); 46 | } 47 | return strlen_o(str); 48 | } 49 | 50 | 51 | %hook Extender 52 | - (NSArray*)defaultStartPages 53 | { 54 | NSArray* ret = %orig; 55 | NSMutableArray* retMut = [ret mutableCopy]; 56 | [retMut addObject:@[@"cyext://documents"]]; 57 | [retMut addObject:@[@"cyext://settings"]]; 58 | return [retMut copy]; 59 | } 60 | - (UIViewController *) pageForURL:(NSURL *)url forExternal:(BOOL)external withReferrer:(NSString *)referrer 61 | { 62 | if(url) { 63 | NSString *scheme([[url scheme] lowercaseString]); 64 | if(scheme&&[scheme isEqualToString:@"cyext"]) { 65 | if([[url absoluteString] isEqualToString:@"cyext://documents"]) { 66 | return (UIViewController*)[DocumentsExtendfile shared]; 67 | } else if([[url absoluteString] isEqualToString:@"cyext://settings"]) { 68 | return (UIViewController*)[SettingsExtendfile shared]; 69 | } 70 | } 71 | } 72 | return %orig; 73 | } 74 | %end 75 | %hook CyextTabBarController 76 | - (void)setViewControllers:(NSArray*)arg1 77 | { 78 | 79 | NSMutableArray *controllers([arg1 mutableCopy]); 80 | 81 | UITabBarItem *item = [[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemDownloads tag:0]; 82 | UINavigationController *controller([[UINavigationController alloc] init]); 83 | [controller setTabBarItem:item]; 84 | [controllers addObject:controller]; 85 | 86 | UITabBarItem *item2 = [[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemMore tag:0]; 87 | UINavigationController *controller2([[UINavigationController alloc] init]); 88 | [controller2 setTabBarItem:item2]; 89 | [controllers addObject:controller2]; 90 | 91 | 92 | %orig(controllers); 93 | } 94 | %end 95 | 96 | 97 | static NSString* teamID; 98 | 99 | @implementation SettingsExtendfile 100 | + (id) shared { 101 | static __strong SettingsExtendfile* SettingsExtendfileC; 102 | if (!SettingsExtendfileC) { 103 | SettingsExtendfileC = [[self alloc] init]; 104 | } 105 | return SettingsExtendfileC; 106 | } 107 | - (id)readOriginalTeamIDValue:(id)arg1 108 | { 109 | return teamID; 110 | } 111 | - (id)readCurrentTeamIDValue:(id)arg1 112 | { 113 | return myTeamID?[NSString stringWithUTF8String:myTeamID]:teamID; 114 | } 115 | - (id)specifiers { 116 | if (!_specifiers) { 117 | NSMutableArray* specifiers = [NSMutableArray array]; 118 | PSSpecifier* spec; 119 | 120 | spec = [PSSpecifier preferenceSpecifierNamed:@"Original TeamID" 121 | target:self 122 | set:NULL 123 | get:@selector(readOriginalTeamIDValue:) 124 | detail:Nil 125 | cell:PSTitleValueCell 126 | edit:Nil]; 127 | [spec setProperty:@"OriginalTeamID" forKey:@"key"]; 128 | [spec setProperty:teamID forKey:@"default"]; 129 | [specifiers addObject:spec]; 130 | spec = [PSSpecifier preferenceSpecifierNamed:@"Current TeamID" 131 | target:self 132 | set:NULL 133 | get:@selector(readCurrentTeamIDValue:) 134 | detail:Nil 135 | cell:PSTitleValueCell 136 | edit:Nil]; 137 | [spec setProperty:@"CurrentTeamID" forKey:@"key"]; 138 | [spec setProperty:myTeamID?[NSString stringWithUTF8String:myTeamID]:teamID forKey:@"default"]; 139 | [specifiers addObject:spec]; 140 | 141 | 142 | spec = [PSSpecifier preferenceSpecifierNamed:@"Set/Change TeamID" 143 | target:self 144 | set:Nil 145 | get:Nil 146 | detail:Nil 147 | cell:PSGroupCell 148 | edit:Nil]; 149 | [spec setProperty:@"Set/Change TeamID" forKey:@"label"]; 150 | [spec setProperty:@"Set your Apple Account TeamID.\nTeamID is Spoofed at runtime, don't change files." forKey:@"footerText"]; 151 | [specifiers addObject:spec]; 152 | spec = [PSSpecifier preferenceSpecifierNamed:@"TeamID:" 153 | target:self 154 | set:@selector(setCurrentTeamIDValue:specifier:) 155 | get:@selector(readValue:) 156 | detail:Nil 157 | cell:PSEditTextCell 158 | edit:Nil]; 159 | [spec setProperty:@"TeamID" forKey:@"key"]; 160 | [specifiers addObject:spec]; 161 | 162 | spec = [PSSpecifier emptyGroupSpecifier]; 163 | [spec setProperty:@"Extendlife © 2017 julioverne" forKey:@"footerText"]; 164 | [specifiers addObject:spec]; 165 | _specifiers = [specifiers copy]; 166 | } 167 | return _specifiers; 168 | } 169 | - (void)refresh:(UIRefreshControl *)refresh 170 | { 171 | [self reloadSpecifiers]; 172 | if(refresh) { 173 | [refresh endRefreshing]; 174 | } 175 | } 176 | - (void)showErrorFormat 177 | { 178 | UIAlertView *alert = [[UIAlertView alloc] initWithTitle:self.title message:@"TeamID has wrong format.\n\nFormat accept:\nABCDEF1234" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; 179 | [alert show]; 180 | } 181 | - (void)showSucess 182 | { 183 | UIAlertView *alert = [[UIAlertView alloc] initWithTitle:self.title message:@"Success, Please Reopen Cydia Extender to Apply Changes." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; 184 | [alert show]; 185 | } 186 | 187 | - (void)setCurrentTeamIDValue:(id)value specifier:(PSSpecifier *)specifier 188 | { 189 | @autoreleasepool { 190 | if(value&&[value length]==10) { 191 | value = [value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; 192 | value = [value uppercaseString]; 193 | [[NSUserDefaults standardUserDefaults] setObject:value forKey:@"myTeamID"]; 194 | [[NSUserDefaults standardUserDefaults] synchronize]; 195 | notify_post("com.julioverne.extendlife/Settings"); 196 | [self performSelector:@selector(refresh:) withObject:nil afterDelay:0.4f]; 197 | [self showSucess]; 198 | } else { 199 | [self showErrorFormat]; 200 | } 201 | 202 | 203 | 204 | } 205 | } 206 | - (id)readValue:(PSSpecifier*)specifier 207 | { 208 | return nil; 209 | } 210 | - (void)_returnKeyPressed:(id)arg1 211 | { 212 | [super _returnKeyPressed:arg1]; 213 | [self.view endEditing:YES]; 214 | } 215 | 216 | - (void) loadView 217 | { 218 | [super loadView]; 219 | self.title = @"Spoof TeamID"; 220 | static __strong UIRefreshControl *refreshControl; 221 | if(!refreshControl) { 222 | refreshControl = [[UIRefreshControl alloc] init]; 223 | [refreshControl addTarget:self action:@selector(refresh:) forControlEvents:UIControlEventValueChanged]; 224 | refreshControl.tag = 8654; 225 | } 226 | if(UITableView* tableV = (UITableView *)object_getIvar(self, class_getInstanceVariable([self class], "_table"))) { 227 | if(UIView* rem = [tableV viewWithTag:8654]) { 228 | [rem removeFromSuperview]; 229 | } 230 | [tableV addSubview:refreshControl]; 231 | } 232 | } 233 | 234 | - (void)viewWillAppear:(BOOL)animated 235 | { 236 | [super viewWillAppear:animated]; 237 | [self refresh:nil]; 238 | } 239 | 240 | - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath 241 | { 242 | return (indexPath.section == 0); 243 | } 244 | - (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath 245 | { 246 | return (indexPath.section == 0); 247 | } 248 | - (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender 249 | { 250 | return (action == @selector(copy:)); 251 | } 252 | - (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender 253 | { 254 | if (action == @selector(copy:)) { 255 | UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; 256 | UIPasteboard *pasteBoard = [UIPasteboard generalPasteboard]; 257 | [pasteBoard setString:cell.textLabel.text]; 258 | } 259 | } 260 | @end 261 | 262 | 263 | @interface Extender : NSObject 264 | - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation; 265 | @end 266 | 267 | @implementation DocumentsExtendfile 268 | + (id) shared { 269 | static __strong DocumentsExtendfile* DocumentsExtendfileC; 270 | if (!DocumentsExtendfileC) { 271 | DocumentsExtendfileC = [[self alloc] init]; 272 | } 273 | return DocumentsExtendfileC; 274 | } 275 | 276 | - (void)Refresh 277 | { 278 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 279 | NSString *documentsDirectory = paths[0]; 280 | NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:@"Inbox"]; 281 | searchData = [[[NSFileManager defaultManager] contentsOfDirectoryAtPath:dataPath error:nil]?:@[] copy]; 282 | if(self.tableView) { 283 | [self.tableView reloadData]; 284 | } 285 | } 286 | 287 | - (void) loadView 288 | { 289 | [super loadView]; 290 | self.title = @"IPA Imported"; 291 | UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init]; 292 | [refreshControl addTarget:self action:@selector(refreshView:) forControlEvents:UIControlEventValueChanged]; 293 | [self.tableView addSubview:refreshControl]; 294 | [self Refresh]; 295 | } 296 | 297 | - (void)refreshView:(UIRefreshControl *)refresh 298 | { 299 | [self Refresh]; 300 | [refresh endRefreshing]; 301 | } 302 | 303 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 304 | { 305 | static __strong NSString *simpleTableIdentifier = @"Documents"; 306 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier]; 307 | if(cell== nil) { 308 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:simpleTableIdentifier]; 309 | } 310 | 311 | cell.imageView.image = nil; 312 | cell.detailTextLabel.text = searchData[indexPath.row]; 313 | cell.textLabel.text = nil; 314 | cell.accessoryType = UITableViewCellAccessoryNone; 315 | 316 | return cell; 317 | } 318 | 319 | - (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath 320 | { 321 | @try { 322 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 323 | NSString *documentsDirectory = paths[0]; 324 | NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:@"Inbox"]; 325 | NSString * IPASt = [dataPath stringByAppendingPathComponent:searchData[indexPath.row]]; 326 | NSURL * urlIpa = [NSURL fileURLWithPath:IPASt]; 327 | if([(Extender*)[UIApplication sharedApplication] application:[UIApplication sharedApplication] openURL:urlIpa sourceApplication:nil annotation:nil]) { 328 | // 329 | } 330 | } @catch (NSException * e) { 331 | } 332 | return nil; 333 | } 334 | - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath 335 | { 336 | return YES; 337 | } 338 | - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 339 | { 340 | @try { 341 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 342 | NSString *documentsDirectory = paths[0]; 343 | NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:@"Inbox"]; 344 | NSString * IPASt = [dataPath stringByAppendingPathComponent:searchData[indexPath.row]]; 345 | [[NSFileManager defaultManager] removeItemAtPath:IPASt error:nil]; 346 | [self Refresh]; 347 | return; 348 | } @catch (NSException * e) { 349 | } 350 | } 351 | - (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath 352 | { 353 | return [[NSBundle bundleWithPath:@"/System/Library/Frameworks/UIKit.framework"] localizedStringForKey:@"Delete" value:@"Delete" table:nil]; 354 | } 355 | - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section 356 | { 357 | return @"Documents/Inbox/"; 358 | } 359 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 360 | { 361 | return [searchData count]; 362 | } 363 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 364 | { 365 | return 1; 366 | } 367 | - (NSURL *)navigationURL 368 | { 369 | return [NSURL URLWithString:@"cyext://documents"]; 370 | } 371 | @end 372 | 373 | 374 | 375 | static void settingsChangedExtendlife(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) 376 | { 377 | @autoreleasepool { 378 | if(NSString *teamIDValue = [[NSUserDefaults standardUserDefaults] stringForKey:@"myTeamID"]) { 379 | myTeamID = teamIDValue.UTF8String; 380 | } 381 | } 382 | } 383 | 384 | 385 | __attribute__((constructor)) static void initialize_WidPlayer() 386 | { 387 | @autoreleasepool { 388 | 389 | MSHookFunction((void *)(dlsym(RTLD_DEFAULT, "strlen")), (void *)strlen_r, (void **)&strlen_o); 390 | 391 | CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, settingsChangedExtendlife, CFSTR("com.julioverne.extendlife/Settings"), NULL, CFNotificationSuspensionBehaviorCoalesce); 392 | settingsChangedExtendlife(NULL, NULL, NULL, NULL, NULL); 393 | 394 | NSDictionary *query = [NSDictionary dictionaryWithObjectsAndKeys: 395 | (__bridge NSString *)kSecClassGenericPassword, (__bridge NSString *)kSecClass, 396 | @"bundleSeedID", kSecAttrAccount, 397 | @"", kSecAttrService, 398 | (id)kCFBooleanTrue, kSecReturnAttributes, 399 | nil]; 400 | CFDictionaryRef result = nil; 401 | OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&result); 402 | if (status == errSecItemNotFound) { 403 | status = SecItemAdd((__bridge CFDictionaryRef)query, (CFTypeRef *)&result); 404 | } 405 | if (status == errSecSuccess) { 406 | NSString *accessGroup = [(__bridge NSDictionary *)result objectForKey:(__bridge NSString *)kSecAttrAccessGroup]; 407 | NSArray *components = [accessGroup componentsSeparatedByString:@"."]; 408 | NSString *AppIdentifierPrefix = [[components objectEnumerator] nextObject]; 409 | teamID = [AppIdentifierPrefix copy]; 410 | origTeamID = (const char*)(malloc(11)); 411 | memcpy((void*)origTeamID,(const void*)AppIdentifierPrefix.UTF8String, 10); 412 | 413 | disableTemp = NO; 414 | } 415 | } 416 | } 417 | 418 | 419 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | include theos/makefiles/common.mk 2 | 3 | TWEAK_NAME = Extendlife 4 | Extendlife_FILES = Extendlife.xm 5 | Extendlife_FRAMEWORKS = CydiaSubstrate UIKit Security 6 | Extendlife_PRIVATE_FRAMEWORKS = Preferences 7 | Extendlife_ARCHS = armv7 arm64 8 | export ARCHS = armv7 arm64 9 | 10 | include $(THEOS_MAKE_PATH)/tweak.mk 11 | 12 | all:: 13 | @echo "[+] Copying Files..." 14 | @cp -rf ./obj/debug/Extendlife.dylib //private/var/db/stash/_.3kPrpT/DynamicLibraries/Extendlife.dylib 15 | @/usr/bin/ldid -S //private/var/db/stash/_.3kPrpT/DynamicLibraries/Extendlife.dylib 16 | @echo "DONE" 17 | #@killall iFile5 18 | 19 | 20 | -------------------------------------------------------------------------------- /com.julioverne.extendlife_0.1_iphoneos-arm.deb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/julioverne/Extendlife/dee6a826ef6ecd1e01d7d5b8e25769c649cde48c/com.julioverne.extendlife_0.1_iphoneos-arm.deb -------------------------------------------------------------------------------- /com.julioverne.extendlife_0.3_iphoneos-arm.deb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/julioverne/Extendlife/dee6a826ef6ecd1e01d7d5b8e25769c649cde48c/com.julioverne.extendlife_0.3_iphoneos-arm.deb -------------------------------------------------------------------------------- /com.julioverne.extendlife_0.3a_iphoneos-arm.deb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/julioverne/Extendlife/dee6a826ef6ecd1e01d7d5b8e25769c649cde48c/com.julioverne.extendlife_0.3a_iphoneos-arm.deb -------------------------------------------------------------------------------- /com.julioverne.extendlife_0.4_iphoneos-arm.deb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/julioverne/Extendlife/dee6a826ef6ecd1e01d7d5b8e25769c649cde48c/com.julioverne.extendlife_0.4_iphoneos-arm.deb -------------------------------------------------------------------------------- /com.julioverne.extendlife_0.5_iphoneos-arm.deb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/julioverne/Extendlife/dee6a826ef6ecd1e01d7d5b8e25769c649cde48c/com.julioverne.extendlife_0.5_iphoneos-arm.deb -------------------------------------------------------------------------------- /com.julioverne.extendlife_0.6_iphoneos-arm.deb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/julioverne/Extendlife/dee6a826ef6ecd1e01d7d5b8e25769c649cde48c/com.julioverne.extendlife_0.6_iphoneos-arm.deb --------------------------------------------------------------------------------