]>
Commit | Line | Data |
---|---|---|
df972f42 | 1 | /* Cydia Substrate - Powerful Code Insertion Platform |
a938d168 | 2 | * Copyright (C) 2008-2010 Jay Freeman (saurik) |
25f84761 JF |
3 | */ |
4 | ||
df972f42 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ |
25f84761 | 6 | /* |
df972f42 JF |
7 | * Cycript is free software: you can redistribute it and/or modify it under |
8 | * the terms of the GNU Lesser General Public License as published by the | |
9 | * Free Software Foundation, either version 3 of the License, or (at your | |
10 | * option) any later version. | |
25f84761 | 11 | * |
df972f42 JF |
12 | * Cycript is distributed in the hope that it will be useful, but WITHOUT |
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public | |
15 | * License for more details. | |
25f84761 | 16 | * |
df972f42 JF |
17 | * You should have received a copy of the GNU Lesser General Public License |
18 | * along with Cycript. If not, see <http://www.gnu.org/licenses/>. | |
19 | **/ | |
20 | /* }}} */ | |
25f84761 JF |
21 | |
22 | #import <CoreFoundation/CoreFoundation.h> | |
23 | #import <Foundation/Foundation.h> | |
24 | #import <CoreGraphics/CGGeometry.h> | |
39f17851 JF |
25 | #import <UIKit/UIKit.h> |
26 | ||
27 | #import <SpringBoard/SBAlertItem.h> | |
28 | #import <SpringBoard/SBAlertItemsController.h> | |
b4f9ed46 | 29 | #import <SpringBoard/SBButtonBar.h> |
39f17851 | 30 | #import <SpringBoard/SBStatusBarController.h> |
e5a54d69 | 31 | #import <SpringBoard/SBStatusBarDataManager.h> |
39f17851 | 32 | #import <SpringBoard/SBStatusBarTimeView.h> |
b4f9ed46 | 33 | #import <SpringBoard/SBUIController.h> |
dbbe0f32 | 34 | |
f6ceb738 | 35 | #include "CydiaSubstrate.h" |
25f84761 | 36 | |
39f17851 JF |
37 | Class $SafeModeAlertItem; |
38 | Class $SBAlertItemsController; | |
39 | ||
40 | void SafeModeAlertItem$alertSheet$buttonClicked$(id self, SEL sel, id sheet, int button) { | |
41 | switch (button) { | |
42 | case 1: | |
43 | break; | |
44 | ||
45 | case 2: | |
46 | exit(0); | |
47 | break; | |
48 | ||
49 | case 3: | |
b4f9ed46 | 50 | [UIApp applicationOpenURL:[NSURL URLWithString:@"http://cydia.saurik.com/safemode/"]]; |
39f17851 JF |
51 | break; |
52 | } | |
53 | ||
54 | [self dismiss]; | |
55 | } | |
56 | ||
57 | void SafeModeAlertItem$configure$requirePasscodeForActions$(id self, SEL sel, BOOL configure, BOOL require) { | |
e5a54d69 | 58 | id sheet([self alertSheet]); |
39f17851 | 59 | [sheet setDelegate:self]; |
b4f9ed46 | 60 | [sheet setBodyText:@"We apologize for the inconvenience, but SpringBoard has just crashed.\n\nMobileSubstrate /did not/ cause this problem: it has protected you from it.\n\nYour device is now running in Safe Mode. All extensions that support this safety system are disabled.\n\nReboot (or restart SpringBoard) to return to the normal mode. To return to this dialog touch the status bar."]; |
39f17851 JF |
61 | [sheet addButtonWithTitle:@"OK"]; |
62 | [sheet addButtonWithTitle:@"Restart"]; | |
63 | [sheet addButtonWithTitle:@"Help"]; | |
64 | [sheet setNumberOfRows:1]; | |
e5a54d69 JF |
65 | if ([sheet respondsToSelector:@selector(setForceHorizontalButtonsLayout:)]) |
66 | [sheet setForceHorizontalButtonsLayout:YES]; | |
39f17851 JF |
67 | } |
68 | ||
69 | void SafeModeAlertItem$performUnlockAction(id self, SEL sel) { | |
70 | [[$SBAlertItemsController sharedInstance] activateAlertItem:self]; | |
71 | } | |
72 | ||
73 | static void MSAlert() { | |
74 | if ($SafeModeAlertItem == nil) | |
75 | $SafeModeAlertItem = objc_lookUpClass("SafeModeAlertItem"); | |
76 | if ($SafeModeAlertItem == nil) { | |
77 | $SafeModeAlertItem = objc_allocateClassPair(objc_getClass("SBAlertItem"), "SafeModeAlertItem", 0); | |
78 | if ($SafeModeAlertItem == nil) | |
79 | return; | |
80 | ||
81 | class_addMethod($SafeModeAlertItem, @selector(alertSheet:buttonClicked:), (IMP) &SafeModeAlertItem$alertSheet$buttonClicked$, "v@:@i"); | |
82 | class_addMethod($SafeModeAlertItem, @selector(configure:requirePasscodeForActions:), (IMP) &SafeModeAlertItem$configure$requirePasscodeForActions$, "v@:cc"); | |
83 | class_addMethod($SafeModeAlertItem, @selector(performUnlockAction), (IMP) SafeModeAlertItem$performUnlockAction, "v@:"); | |
84 | objc_registerClassPair($SafeModeAlertItem); | |
85 | } | |
86 | ||
87 | if ($SBAlertItemsController != nil) | |
a938d168 | 88 | [[$SBAlertItemsController sharedInstance] activateAlertItem:[[[$SafeModeAlertItem alloc] init] autorelease]]; |
39f17851 JF |
89 | } |
90 | ||
b4f9ed46 JF |
91 | MSHook(void, SBStatusBar$touchesEnded$withEvent$, SBStatusBar *self, SEL sel, id touches, id event) { |
92 | MSAlert(); | |
93 | _SBStatusBar$touchesEnded$withEvent$(self, sel, touches, event); | |
94 | } | |
95 | ||
39f17851 JF |
96 | MSHook(void, SBStatusBar$mouseDown$, SBStatusBar *self, SEL sel, GSEventRef event) { |
97 | MSAlert(); | |
98 | _SBStatusBar$mouseDown$(self, sel, event); | |
99 | } | |
100 | ||
e5a54d69 JF |
101 | MSHook(void, UIStatusBar$touchesBegan$withEvent$, id self, SEL sel, void *arg0, void *arg1) { |
102 | MSAlert(); | |
103 | _UIStatusBar$touchesBegan$withEvent$(self, sel, arg0, arg1); | |
104 | } | |
105 | ||
106 | MSHook(void, SBStatusBarDataManager$_updateTimeString, id self, SEL sel) { | |
107 | if (char *_data = &MSHookIvar<char>(self, "_data")) { | |
108 | char *timeString(_data + 20); | |
109 | strcpy(timeString, "Exit Safe Mode"); | |
110 | } | |
111 | } | |
112 | ||
39f17851 | 113 | static void SBIconController$showInfoAlertIfNeeded(id self, SEL sel) { |
25f84761 | 114 | static bool loaded = false; |
39f17851 JF |
115 | if (loaded) |
116 | return; | |
117 | loaded = true; | |
118 | MSAlert(); | |
25f84761 JF |
119 | } |
120 | ||
b4f9ed46 | 121 | MSHook(int, SBButtonBar$maxIconColumns, SBButtonBar *self, SEL sel) { |
25f84761 JF |
122 | static int max; |
123 | if (max == 0) { | |
b4f9ed46 | 124 | max = _SBButtonBar$maxIconColumns(self, sel); |
25f84761 JF |
125 | if (NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]) |
126 | if (NSDictionary *iconState = [defaults objectForKey:@"iconState"]) | |
127 | if (NSDictionary *buttonBar = [iconState objectForKey:@"buttonBar"]) | |
128 | if (NSArray *iconMatrix = [buttonBar objectForKey:@"iconMatrix"]) | |
129 | if ([iconMatrix count] != 0) | |
130 | if (NSArray *row = [iconMatrix objectAtIndex:0]) { | |
131 | int count([row count]); | |
132 | if (max < count) | |
133 | max = count; | |
134 | } | |
135 | } return max; | |
136 | } | |
137 | ||
b4f9ed46 JF |
138 | MSHook(id, SBUIController$init, SBUIController *self, SEL sel) { |
139 | if ((self = _SBUIController$init(self, sel)) != nil) { | |
140 | UIView *&_contentLayer(MSHookIvar<UIView *>(self, "_contentLayer")); | |
141 | UIView *&_contentView(MSHookIvar<UIView *>(self, "_contentView")); | |
142 | ||
143 | UIView *layer; | |
144 | if (&_contentLayer != NULL) | |
145 | layer = _contentLayer; | |
146 | else if (&_contentView != NULL) | |
147 | layer = _contentView; | |
148 | else | |
149 | layer = nil; | |
150 | ||
151 | if (layer != nil) | |
152 | [layer setBackgroundColor:[UIColor darkGrayColor]]; | |
153 | } return self; | |
25f84761 JF |
154 | } |
155 | ||
dbbe0f32 JF |
156 | #define Paper_ "/Library/MobileSubstrate/MobilePaper.png" |
157 | ||
158 | MSHook(UIImage *, UIImage$defaultDesktopImage, UIImage *self, SEL sel) { | |
159 | return [UIImage imageWithContentsOfFile:@Paper_]; | |
160 | } | |
161 | ||
39f17851 JF |
162 | MSHook(void, SBStatusBarTimeView$tile, SBStatusBarTimeView *self, SEL sel) { |
163 | NSString *&_time(MSHookIvar<NSString *>(self, "_time")); | |
164 | CGRect &_textRect(MSHookIvar<CGRect>(self, "_textRect")); | |
25f84761 | 165 | if (_time != nil) |
39f17851 | 166 | [_time release]; |
dbbe0f32 | 167 | _time = [@"Exit Safe Mode" retain]; |
39f17851 JF |
168 | GSFontRef font([self textFont]); |
169 | CGSize size([_time sizeWithFont:(id)font]); | |
170 | CGRect frame([self frame]); | |
39f17851 JF |
171 | _textRect.size = size; |
172 | _textRect.origin.x = (frame.size.width - size.width) / 2; | |
173 | _textRect.origin.y = (frame.size.height - size.height) / 2; | |
25f84761 JF |
174 | } |
175 | ||
176 | #define Dylib_ "/Library/MobileSubstrate/MobileSubstrate.dylib" | |
177 | ||
63918068 | 178 | MSInitialize { |
10586051 JF |
179 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; |
180 | ||
25f84761 JF |
181 | NSLog(@"MS:Warning: Entering Safe Mode"); |
182 | ||
b4f9ed46 JF |
183 | _SBButtonBar$maxIconColumns = MSHookMessage(objc_getClass("SBButtonBar"), @selector(maxIconColumns), &$SBButtonBar$maxIconColumns); |
184 | _SBUIController$init = MSHookMessage(objc_getClass("SBUIController"), @selector(init), &$SBUIController$init); | |
185 | _SBStatusBar$touchesEnded$withEvent$ = MSHookMessage(objc_getClass("SBStatusBar"), @selector(touchesEnded:withEvent:), &$SBStatusBar$touchesEnded$withEvent$); | |
39f17851 | 186 | _SBStatusBar$mouseDown$ = MSHookMessage(objc_getClass("SBStatusBar"), @selector(mouseDown:), &$SBStatusBar$mouseDown$); |
e5a54d69 | 187 | _SBStatusBarDataManager$_updateTimeString = MSHookMessage(objc_getClass("SBStatusBarDataManager"), @selector(_updateTimeString), &$SBStatusBarDataManager$_updateTimeString); |
39f17851 | 188 | _SBStatusBarTimeView$tile = MSHookMessage(objc_getClass("SBStatusBarTimeView"), @selector(tile), &$SBStatusBarTimeView$tile); |
25f84761 | 189 | |
e5a54d69 JF |
190 | _UIStatusBar$touchesBegan$withEvent$ = MSHookMessage(objc_getClass("UIStatusBar"), @selector(touchesBegan:withEvent:), &$UIStatusBar$touchesBegan$withEvent$); |
191 | ||
dbbe0f32 | 192 | _UIImage$defaultDesktopImage = MSHookMessage(object_getClass(objc_getClass("UIImage")), @selector(defaultDesktopImage), &$UIImage$defaultDesktopImage); |
dbbe0f32 | 193 | |
25f84761 JF |
194 | char *dil = getenv("DYLD_INSERT_LIBRARIES"); |
195 | if (dil == NULL) | |
196 | NSLog(@"MS:Error: DYLD_INSERT_LIBRARIES is unset?"); | |
197 | else { | |
198 | NSArray *dylibs([[NSString stringWithUTF8String:dil] componentsSeparatedByString:@":"]); | |
199 | NSUInteger index([dylibs indexOfObject:@ Dylib_]); | |
200 | if (index == NSNotFound) | |
201 | NSLog(@"MS:Error: dylib not in DYLD_INSERT_LIBRARIES?"); | |
202 | else if ([dylibs count] == 1) | |
203 | unsetenv("DYLD_INSERT_LIBRARIES"); | |
204 | else { | |
205 | NSMutableArray *value([[[NSMutableArray alloc] init] autorelease]); | |
206 | [value setArray:dylibs]; | |
207 | [value removeObjectAtIndex:index]; | |
208 | setenv("DYLD_INSERT_LIBRARIES", [[value componentsJoinedByString:@":"] UTF8String], !0); | |
209 | } | |
210 | } | |
211 | ||
39f17851 JF |
212 | $SBAlertItemsController = objc_getClass("SBAlertItemsController"); |
213 | ||
25f84761 JF |
214 | if (Class _class = objc_getClass("SBIconController")) { |
215 | SEL sel(@selector(showInfoAlertIfNeeded)); | |
216 | if (Method method = class_getInstanceMethod(_class, sel)) | |
39f17851 | 217 | method_setImplementation(method, (IMP) &SBIconController$showInfoAlertIfNeeded); |
25f84761 | 218 | } |
10586051 JF |
219 | |
220 | [pool release]; | |
25f84761 | 221 | } |