├── .gitattributes ├── Makefile ├── lowerinstallhooks ├── LowerInstall.xm └── Makefile └── lowerinstallsettings ├── LowerInstallSettingsController.mm └── Makefile /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | include $(THEOS)/makefiles/common.mk 2 | 3 | SUBPROJECTS += lowerinstallhooks 4 | SUBPROJECTS += lowerinstallsettings 5 | 6 | include $(THEOS_MAKE_PATH)/aggregate.mk 7 | -------------------------------------------------------------------------------- /lowerinstallhooks/LowerInstall.xm: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | #import 5 | #import 6 | 7 | extern const char *__progname; 8 | 9 | #define NSLog(...) 10 | 11 | #define PLIST_PATH_Settings "/var/mobile/Library/Preferences/com.julioverne.lowerinstall.plist" 12 | 13 | 14 | static BOOL Enabled; 15 | 16 | typedef enum { 17 | kUserAgent=0, 18 | kUserAgentFormat=1, 19 | kCurrentDeviceType=2, 20 | kCurrentiOSVersion=3, 21 | kSpoofDeviceType=4, 22 | kSpoofiOSVersion=5, 23 | } LowerInstall_var_Num; 24 | 25 | #define MAX_STRING_LEN 30 26 | #define STORED_STRING LowerInstall_var7956 27 | 28 | char STORED_STRING[10][MAX_STRING_LEN]; 29 | #define StringVal(VALUE_ST) [NSString stringWithUTF8String:STORED_STRING[VALUE_ST]] 30 | 31 | 32 | %group itunesstoredHooks 33 | 34 | %hook NSMutableURLRequest 35 | 36 | - (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field 37 | { 38 | if((Enabled && field && value) && [field isEqualToString:StringVal(kUserAgent)]) { 39 | if([value rangeOfString:StringVal(kCurrentiOSVersion)].location != NSNotFound) { 40 | value = [value stringByReplacingOccurrencesOfString:[NSString stringWithFormat:StringVal(kUserAgentFormat), StringVal(kCurrentiOSVersion)] withString:[NSString stringWithFormat:StringVal(kUserAgentFormat), StringVal(kSpoofiOSVersion)]]; 41 | value = [value stringByReplacingOccurrencesOfString:[NSString stringWithFormat:StringVal(kUserAgentFormat), StringVal(kCurrentDeviceType)] withString:[NSString stringWithFormat:StringVal(kUserAgentFormat), StringVal(kSpoofDeviceType)]]; 42 | } 43 | } 44 | %orig(value, field); 45 | } 46 | 47 | %end 48 | 49 | %end 50 | 51 | %group installdHooks 52 | 53 | %hook MIDaemonConfiguration 54 | 55 | - (BOOL)skipDeviceFamilyCheck 56 | { 57 | if(Enabled) { 58 | return YES; 59 | } 60 | return %orig; 61 | } 62 | 63 | - (BOOL)skipThinningCheck 64 | { 65 | if(Enabled) { 66 | return YES; 67 | } 68 | return %orig; 69 | } 70 | 71 | %end 72 | 73 | %hook MIBundle 74 | 75 | - (NSString*)minimumOSVersion 76 | { 77 | NSString* ret = %orig; 78 | if(Enabled) { 79 | ret = @"2.0"; 80 | } 81 | return ret; 82 | } 83 | 84 | - (NSArray *)supportedDevices 85 | { 86 | NSArray* ret = %orig?:@[]; 87 | if(Enabled && ![ret containsObject:StringVal(kCurrentDeviceType)]) { 88 | NSMutableArray* retMut = [ret mutableCopy]; 89 | [retMut addObject:StringVal(kCurrentDeviceType)]; 90 | ret = [retMut copy]; 91 | } 92 | return ret; 93 | } 94 | 95 | - (BOOL)isCompatibleWithDeviceFamily:(int)device 96 | { 97 | if(Enabled) { 98 | return YES; 99 | } 100 | return %orig; 101 | } 102 | - (BOOL)isApplicableToCurrentDeviceFamilyWithError:(id*)error 103 | { 104 | if(Enabled) { 105 | return YES; 106 | } 107 | return %orig; 108 | } 109 | - (BOOL)isApplicableToCurrentOSVersionWithError:(id*)error 110 | { 111 | if(Enabled) { 112 | return YES; 113 | } 114 | return %orig; 115 | } 116 | - (BOOL)isApplicableToOSVersion:(id)arg1 error:(id*)error 117 | { 118 | if(Enabled) { 119 | return YES; 120 | } 121 | return %orig; 122 | } 123 | - (BOOL)isApplicableToCurrentDeviceCapabilitiesWithError:(id*)error 124 | { 125 | if(Enabled) { 126 | return YES; 127 | } 128 | return %orig; 129 | } 130 | - (BOOL)thinningMatchesCurrentDeviceWithError:(id*)error 131 | { 132 | if(Enabled) { 133 | return YES; 134 | } 135 | return %orig; 136 | } 137 | 138 | - (BOOL)validateAppMetadataWithError:(id*)error 139 | { 140 | if(Enabled) { 141 | return YES; 142 | } 143 | return %orig; 144 | } 145 | 146 | - (BOOL)validatePluginMetadataWithError:(id*)error 147 | { 148 | if(Enabled) { 149 | return YES; 150 | } 151 | return %orig; 152 | } 153 | 154 | %end 155 | 156 | %hook MIInstallableBundle 157 | 158 | -(BOOL)_validateApplicationIdentifierForNewBundleSigningInfo:(id)arg1 error:(id *)arg2 159 | { 160 | if(Enabled) { 161 | return YES; 162 | } 163 | return %orig; 164 | } 165 | 166 | -(BOOL)_verifyBundleMetadataWithError:(id*)error 167 | { 168 | if(Enabled) { 169 | return YES; 170 | } 171 | return %orig; 172 | } 173 | 174 | -(BOOL)_verifySubBundleMetadataWithError:(id*)error 175 | { 176 | if(Enabled) { 177 | return YES; 178 | } 179 | return %orig; 180 | } 181 | 182 | 183 | // wa 184 | -(BOOL)_isValidWatchKitApp:(id)arg1 withVersion:(id)arg2 installableSigningInfo:(id)arg3 error:(id *)arg4 185 | { 186 | if(Enabled) { 187 | return YES; 188 | } 189 | return %orig; 190 | } 191 | 192 | 193 | %end 194 | 195 | 196 | %hook MIExecutableBundle 197 | //wa 198 | - (BOOL)hasOnlyAllowedWatchKitAppInfoPlistKeysForWatchKitVersion:(id)arg1 error:(id*)arg2 199 | { 200 | if(Enabled) { 201 | return YES; 202 | } 203 | return %orig; 204 | } 205 | 206 | %end 207 | 208 | 209 | %hook MIPluginKitPluginBundle 210 | 211 | - (BOOL)validateBundleMetadataWithError:(id*)error 212 | { 213 | if(Enabled) { 214 | return YES; 215 | } 216 | return %orig; 217 | } 218 | 219 | %end 220 | 221 | 222 | %end 223 | 224 | static void settingsChangedLowerInstall() 225 | { 226 | @autoreleasepool { 227 | NSDictionary *LowerInstallPrefs = [[[NSDictionary alloc] initWithContentsOfFile:@PLIST_PATH_Settings]?:[NSDictionary dictionary] copy]; 228 | Enabled = (BOOL)[[LowerInstallPrefs objectForKey:@"Enabled"]?:@YES boolValue]; 229 | 230 | NSString* CurrentDeviceTypeSpoof = [LowerInstallPrefs objectForKey:@"SpoofDevice"]?:StringVal(kCurrentDeviceType); 231 | bzero(STORED_STRING[kSpoofDeviceType], MAX_STRING_LEN); 232 | memcpy(STORED_STRING[kSpoofDeviceType],(const void*)CurrentDeviceTypeSpoof.UTF8String, [CurrentDeviceTypeSpoof length]); 233 | 234 | NSString* CurrentiOSVersionSpoof = [LowerInstallPrefs objectForKey:@"SpoofVersion"]?:StringVal(kCurrentiOSVersion); 235 | bzero(STORED_STRING[kSpoofiOSVersion], MAX_STRING_LEN); 236 | memcpy(STORED_STRING[kSpoofiOSVersion],(const void*)CurrentiOSVersionSpoof.UTF8String, [CurrentiOSVersionSpoof length]); 237 | } 238 | } 239 | 240 | %ctor 241 | { 242 | bzero(STORED_STRING[kUserAgent], MAX_STRING_LEN); 243 | strcpy(STORED_STRING[kUserAgent], "User-Agent"); 244 | 245 | bzero(STORED_STRING[kUserAgentFormat], MAX_STRING_LEN); 246 | strcpy(STORED_STRING[kUserAgentFormat], "/%@ "); 247 | 248 | struct utsname systemInfo; 249 | uname(&systemInfo); 250 | bzero(STORED_STRING[kCurrentDeviceType], MAX_STRING_LEN); 251 | strcpy(STORED_STRING[kCurrentDeviceType], systemInfo.machine); 252 | 253 | bzero(STORED_STRING[kCurrentiOSVersion], MAX_STRING_LEN); 254 | strcpy(STORED_STRING[kCurrentiOSVersion], [NSString stringWithFormat:@"%@", [[UIDevice currentDevice] systemVersion]].UTF8String); 255 | 256 | CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, (CFNotificationCallback)settingsChangedLowerInstall, CFSTR("com.julioverne.lowerinstall/SettingsChanged"), NULL, CFNotificationSuspensionBehaviorCoalesce); 257 | settingsChangedLowerInstall(); 258 | 259 | if(strcmp(__progname, "itunesstored") == 0) { 260 | %init(itunesstoredHooks); 261 | } else { 262 | %init(installdHooks); 263 | } 264 | } -------------------------------------------------------------------------------- /lowerinstallhooks/Makefile: -------------------------------------------------------------------------------- 1 | include $(THEOS)/makefiles/common.mk 2 | 3 | TWEAK_NAME = LowerInstall 4 | 5 | $(TWEAK_NAME)_FILES = /mnt/d/codes/lowerinstall/lowerinstallhooks/LowerInstall.xm 6 | $(TWEAK_NAME)_FRAMEWORKS = CydiaSubstrate Foundation UIKit 7 | $(TWEAK_NAME)_LDFLAGS = -Wl,-segalign,4000 8 | 9 | export ARCHS = armv7 armv7s arm64 arm64e 10 | $(TWEAK_NAME)_ARCHS = armv7 armv7s arm64 arm64e 11 | 12 | include $(THEOS_MAKE_PATH)/tweak.mk 13 | -------------------------------------------------------------------------------- /lowerinstallsettings/LowerInstallSettingsController.mm: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | #import 5 | #import 6 | 7 | #define NSLog(...) 8 | 9 | #define PLIST_PATH_Settings "/var/mobile/Library/Preferences/com.julioverne.lowerinstall.plist" 10 | 11 | @interface LowerInstallSettingsController : PSListController 12 | { 13 | UILabel* _label; 14 | UILabel* underLabel; 15 | } 16 | - (void)HeaderCell; 17 | @end 18 | 19 | @implementation LowerInstallSettingsController 20 | - (id)specifiers { 21 | if (!_specifiers) { 22 | NSMutableArray* specifiers = [NSMutableArray array]; 23 | PSSpecifier* spec; 24 | 25 | spec = [PSSpecifier preferenceSpecifierNamed:@"Enabled" 26 | target:self 27 | set:@selector(setPreferenceValue:specifier:) 28 | get:@selector(readPreferenceValue:) 29 | detail:Nil 30 | cell:PSSwitchCell 31 | edit:Nil]; 32 | [spec setProperty:@"Enabled" forKey:@"key"]; 33 | [spec setProperty:@YES forKey:@"default"]; 34 | [specifiers addObject:spec]; 35 | 36 | spec = [PSSpecifier preferenceSpecifierNamed:@"Information Spoof" 37 | target:self 38 | set:Nil 39 | get:Nil 40 | detail:Nil 41 | cell:PSGroupCell 42 | edit:Nil]; 43 | [spec setProperty:@"iOS Version" forKey:@"label"]; 44 | [spec setProperty:@"Input Device Detail you want to Spoof for allow install." forKey:@"footerText"]; 45 | [specifiers addObject:spec]; 46 | 47 | struct utsname systemInfo; 48 | uname(&systemInfo); 49 | NSString* kCurrentDeviceType = [NSString stringWithFormat:@"%s", systemInfo.machine]; 50 | NSString* kCurrentiOSVersion = [NSString stringWithFormat:@"%@", [[UIDevice currentDevice] systemVersion]]; 51 | 52 | spec = [PSSpecifier preferenceSpecifierNamed:@"iOS Version" 53 | target:self 54 | set:@selector(setPreferenceValue:specifier:) 55 | get:@selector(readPreferenceValue:) 56 | detail:Nil 57 | cell:PSEditTextCell 58 | edit:Nil]; 59 | [spec setProperty:@"SpoofVersion" forKey:@"key"]; 60 | [spec setProperty:kCurrentiOSVersion forKey:@"default"]; 61 | [specifiers addObject:spec]; 62 | spec = [PSSpecifier preferenceSpecifierNamed:@"Device" 63 | target:self 64 | set:@selector(setPreferenceValue:specifier:) 65 | get:@selector(readPreferenceValue:) 66 | detail:Nil 67 | cell:PSEditTextCell 68 | edit:Nil]; 69 | [spec setProperty:@"SpoofDevice" forKey:@"key"]; 70 | [spec setProperty:kCurrentDeviceType forKey:@"default"]; 71 | [specifiers addObject:spec]; 72 | 73 | 74 | spec = [PSSpecifier emptyGroupSpecifier]; 75 | [specifiers addObject:spec]; 76 | spec = [PSSpecifier preferenceSpecifierNamed:@"Reset Settings" 77 | target:self 78 | set:NULL 79 | get:NULL 80 | detail:Nil 81 | cell:PSLinkCell 82 | edit:Nil]; 83 | spec->action = @selector(reset); 84 | [specifiers addObject:spec]; 85 | spec = [PSSpecifier preferenceSpecifierNamed:@"Developer" 86 | target:self 87 | set:Nil 88 | get:Nil 89 | detail:Nil 90 | cell:PSGroupCell 91 | edit:Nil]; 92 | [spec setProperty:@"Developer" forKey:@"label"]; 93 | [specifiers addObject:spec]; 94 | spec = [PSSpecifier preferenceSpecifierNamed:@"Follow julioverne" 95 | target:self 96 | set:NULL 97 | get:NULL 98 | detail:Nil 99 | cell:PSLinkCell 100 | edit:Nil]; 101 | spec->action = @selector(twitter); 102 | [spec setProperty:@YES forKey:@"hasIcon"]; 103 | [spec setProperty:[UIImage imageWithContentsOfFile:[[self bundle] pathForResource:@"twitter" ofType:@"png"]] forKey:@"iconImage"]; 104 | [specifiers addObject:spec]; 105 | spec = [PSSpecifier emptyGroupSpecifier]; 106 | [spec setProperty:@"LowerInstall © 2022" forKey:@"footerText"]; 107 | [specifiers addObject:spec]; 108 | _specifiers = [specifiers copy]; 109 | } 110 | return _specifiers; 111 | } 112 | - (void)twitter 113 | { 114 | UIApplication *app = [UIApplication sharedApplication]; 115 | if ([app canOpenURL:[NSURL URLWithString:@"twitter://user?screen_name=ijulioverne"]]) { 116 | [app openURL:[NSURL URLWithString:@"twitter://user?screen_name=ijulioverne"]]; 117 | } else if ([app canOpenURL:[NSURL URLWithString:@"tweetbot:///user_profile/ijulioverne"]]) { 118 | [app openURL:[NSURL URLWithString:@"tweetbot:///user_profile/ijulioverne"]]; 119 | } else { 120 | [app openURL:[NSURL URLWithString:@"https://mobile.twitter.com/ijulioverne"]]; 121 | } 122 | } 123 | - (void)love 124 | { 125 | SLComposeViewController *twitter = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeTwitter]; 126 | [twitter setInitialText:@"#LowerInstall by @ijulioverne is cool!"]; 127 | if (twitter != nil) { 128 | [[self navigationController] presentViewController:twitter animated:YES completion:nil]; 129 | } 130 | } 131 | - (void)showPrompt 132 | { 133 | UIAlertView *alert = [[UIAlertView alloc] initWithTitle:self.title message:@"An Respring is Requerid for this option." delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Respring", nil]; 134 | alert.tag = 55; 135 | [alert show]; 136 | } 137 | - (void)reset 138 | { 139 | [@{} writeToFile:@PLIST_PATH_Settings atomically:YES]; 140 | notify_post("com.julioverne.lowerinstall/SettingsChanged"); 141 | [self reloadSpecifiers]; 142 | [self showPrompt]; 143 | } 144 | 145 | - (void)setPreferenceValue:(id)value specifier:(PSSpecifier *)specifier 146 | { 147 | @autoreleasepool { 148 | NSMutableDictionary *Prefs = [[NSMutableDictionary alloc] initWithContentsOfFile:@PLIST_PATH_Settings]?:[NSMutableDictionary dictionary]; 149 | Prefs[[specifier identifier]] = value; 150 | [Prefs writeToFile:@PLIST_PATH_Settings atomically:YES]; 151 | notify_post("com.julioverne.lowerinstall/SettingsChanged"); 152 | if ([[specifier properties] objectForKey:@"PromptRespring"]) { 153 | [self showPrompt]; 154 | } 155 | } 156 | } 157 | - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex 158 | { 159 | if (alertView.tag == 55 && buttonIndex == 1) { 160 | system("killall backboardd SpringBoard"); 161 | } 162 | } 163 | - (id)readPreferenceValue:(PSSpecifier*)specifier 164 | { 165 | @autoreleasepool { 166 | NSDictionary *Prefs = [[NSDictionary alloc] initWithContentsOfFile:@PLIST_PATH_Settings]; 167 | return Prefs[[specifier identifier]]?:[specifier properties][@"default"]; 168 | } 169 | } 170 | - (void)_returnKeyPressed:(id)arg1 171 | { 172 | [super _returnKeyPressed:arg1]; 173 | [self.view endEditing:YES]; 174 | } 175 | 176 | - (void)HeaderCell 177 | { 178 | @autoreleasepool { 179 | UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 120)]; 180 | int width = [[UIScreen mainScreen] bounds].size.width; 181 | CGRect frame = CGRectMake(0, 20, width, 60); 182 | CGRect botFrame = CGRectMake(0, 55, width, 60); 183 | _label = [[UILabel alloc] initWithFrame:frame]; 184 | [_label setNumberOfLines:1]; 185 | _label.font = [UIFont fontWithName:@"HelveticaNeue-UltraLight" size:48]; 186 | [_label setText:@"LowerInstall"]; 187 | [_label setBackgroundColor:[UIColor clearColor]]; 188 | _label.textColor = [UIColor blackColor]; 189 | _label.textAlignment = NSTextAlignmentCenter; 190 | _label.alpha = 0; 191 | 192 | underLabel = [[UILabel alloc] initWithFrame:botFrame]; 193 | [underLabel setNumberOfLines:1]; 194 | underLabel.font = [UIFont fontWithName:@"HelveticaNeue-Light" size:14]; 195 | [underLabel setText:@"Install Apps In Lower iOS Version"]; 196 | [underLabel setBackgroundColor:[UIColor clearColor]]; 197 | underLabel.textColor = [UIColor grayColor]; 198 | underLabel.textAlignment = NSTextAlignmentCenter; 199 | underLabel.alpha = 0; 200 | 201 | [headerView addSubview:_label]; 202 | [headerView addSubview:underLabel]; 203 | 204 | [_table setTableHeaderView:headerView]; 205 | [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(increaseAlpha) userInfo:nil repeats:NO]; 206 | } 207 | } 208 | - (void) loadView 209 | { 210 | [super loadView]; 211 | self.title = @"LowerInstall"; 212 | [UISwitch appearanceWhenContainedIn:self.class, nil].onTintColor = [UIColor colorWithRed:0.09 green:0.99 blue:0.99 alpha:1.0]; 213 | UIButton *heart = [[UIButton alloc] initWithFrame:CGRectZero]; 214 | [heart setImage:[[UIImage alloc] initWithContentsOfFile:[[self bundle] pathForResource:@"Heart" ofType:@"png"]] forState:UIControlStateNormal]; 215 | [heart sizeToFit]; 216 | [heart addTarget:self action:@selector(love) forControlEvents:UIControlEventTouchUpInside]; 217 | self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:heart]; 218 | [self HeaderCell]; 219 | } 220 | - (void)increaseAlpha 221 | { 222 | [UIView animateWithDuration:0.5 animations:^{ 223 | _label.alpha = 1; 224 | }completion:^(BOOL finished) { 225 | [UIView animateWithDuration:0.5 animations:^{ 226 | underLabel.alpha = 1; 227 | }completion:nil]; 228 | }]; 229 | } 230 | @end 231 | -------------------------------------------------------------------------------- /lowerinstallsettings/Makefile: -------------------------------------------------------------------------------- 1 | include $(THEOS)/makefiles/common.mk 2 | 3 | BUNDLE_NAME = LowerInstallSettings 4 | $(BUNDLE_NAME)_FILES = /mnt/d/codes/lowerinstall/lowerinstallsettings/LowerInstallSettingsController.mm 5 | $(BUNDLE_NAME)_INSTALL_PATH = /Library/PreferenceBundles 6 | $(BUNDLE_NAME)_FRAMEWORKS = UIKit QuartzCore CoreGraphics MessageUI Social Twitter 7 | $(BUNDLE_NAME)_PRIVATE_FRAMEWORKS = Preferences 8 | $(BUNDLE_NAME)_CFLAGS = -fobjc-arc 9 | 10 | $(BUNDLE_NAME)_ARCHS = armv7 armv7s arm64 arm64e 11 | export ARCHS = armv7 armv7s arm64 arm64e 12 | 13 | include $(THEOS_MAKE_PATH)/bundle.mk 14 | --------------------------------------------------------------------------------