]> git.saurik.com Git - safemode-ios.git/blame - MobileSafety.mm
Added MobilePaper and replaced RESETHAND.
[safemode-ios.git] / MobileSafety.mm
CommitLineData
25f84761
JF
1/* Cydia Substrate - Meta-Library Insert for iPhoneOS
2 * Copyright (C) 2008 Jay Freeman (saurik)
3*/
4
5/*
6 * Redistribution and use in source and binary
7 * forms, with or without modification, are permitted
8 * provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the
11 * above copyright notice, this list of conditions
12 * and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the
14 * above copyright notice, this list of conditions
15 * and the following disclaimer in the documentation
16 * and/or other materials provided with the
17 * distribution.
18 * 3. The name of the author may not be used to endorse
19 * or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
24 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
33 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
35 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36*/
37
38#import <CoreFoundation/CoreFoundation.h>
39#import <Foundation/Foundation.h>
40#import <CoreGraphics/CGGeometry.h>
39f17851
JF
41#import <UIKit/UIKit.h>
42
43#import <SpringBoard/SBAlertItem.h>
44#import <SpringBoard/SBAlertItemsController.h>
45#import <SpringBoard/SBContentLayer.h>
46#import <SpringBoard/SBStatusBarController.h>
47#import <SpringBoard/SBStatusBarTimeView.h>
25f84761 48
dbbe0f32
JF
49#import <SpringBoard/SBSlidingAlertDisplay.h>
50
25f84761
JF
51#include <substrate.h>
52
53@protocol MobileSubstrate
25f84761 54- (id) ms$initWithSize:(CGSize)size;
25f84761
JF
55- (int) ms$maxIconColumns;
56@end
57
39f17851
JF
58Class $SafeModeAlertItem;
59Class $SBAlertItemsController;
60
61void SafeModeAlertItem$alertSheet$buttonClicked$(id self, SEL sel, id sheet, int button) {
62 switch (button) {
63 case 1:
64 break;
65
66 case 2:
67 exit(0);
68 break;
69
70 case 3:
d524c4d8 71 [UIApp applicationOpenURL:[NSURL URLWithString:@"http://cydia.saurik.com/safemode/"] asPanel:NO];
39f17851
JF
72 break;
73 }
74
75 [self dismiss];
76}
77
78void SafeModeAlertItem$configure$requirePasscodeForActions$(id self, SEL sel, BOOL configure, BOOL require) {
79 UIModalView *sheet([self alertSheet]);
80 [sheet setDelegate:self];
81 [sheet setBodyText:@"We apologize for the inconvenience, but SpringBoard has just crashed.\n\nA recent software installation, upgrade, or removal might have been the cause of this.\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."];
82 [sheet addButtonWithTitle:@"OK"];
83 [sheet addButtonWithTitle:@"Restart"];
84 [sheet addButtonWithTitle:@"Help"];
85 [sheet setNumberOfRows:1];
86}
87
88void SafeModeAlertItem$performUnlockAction(id self, SEL sel) {
89 [[$SBAlertItemsController sharedInstance] activateAlertItem:self];
90}
91
92static void MSAlert() {
93 if ($SafeModeAlertItem == nil)
94 $SafeModeAlertItem = objc_lookUpClass("SafeModeAlertItem");
95 if ($SafeModeAlertItem == nil) {
96 $SafeModeAlertItem = objc_allocateClassPair(objc_getClass("SBAlertItem"), "SafeModeAlertItem", 0);
97 if ($SafeModeAlertItem == nil)
98 return;
99
100 class_addMethod($SafeModeAlertItem, @selector(alertSheet:buttonClicked:), (IMP) &SafeModeAlertItem$alertSheet$buttonClicked$, "v@:@i");
101 class_addMethod($SafeModeAlertItem, @selector(configure:requirePasscodeForActions:), (IMP) &SafeModeAlertItem$configure$requirePasscodeForActions$, "v@:cc");
102 class_addMethod($SafeModeAlertItem, @selector(performUnlockAction), (IMP) SafeModeAlertItem$performUnlockAction, "v@:");
103 objc_registerClassPair($SafeModeAlertItem);
104 }
105
106 if ($SBAlertItemsController != nil)
107 [[$SBAlertItemsController sharedInstance] activateAlertItem:[[$SafeModeAlertItem alloc] init]];
108}
109
110MSHook(void, SBStatusBar$mouseDown$, SBStatusBar *self, SEL sel, GSEventRef event) {
111 MSAlert();
112 _SBStatusBar$mouseDown$(self, sel, event);
113}
114
115static void SBIconController$showInfoAlertIfNeeded(id self, SEL sel) {
25f84761 116 static bool loaded = false;
39f17851
JF
117 if (loaded)
118 return;
119 loaded = true;
120 MSAlert();
25f84761
JF
121}
122
123static int SBButtonBar$maxIconColumns(id<MobileSubstrate> self, SEL sel) {
124 static int max;
125 if (max == 0) {
126 max = [self ms$maxIconColumns];
127 if (NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults])
128 if (NSDictionary *iconState = [defaults objectForKey:@"iconState"])
129 if (NSDictionary *buttonBar = [iconState objectForKey:@"buttonBar"])
130 if (NSArray *iconMatrix = [buttonBar objectForKey:@"iconMatrix"])
131 if ([iconMatrix count] != 0)
132 if (NSArray *row = [iconMatrix objectAtIndex:0]) {
133 int count([row count]);
134 if (max < count)
135 max = count;
136 }
137 } return max;
138}
139
39f17851 140static id SBContentLayer$initWithSize$(SBContentLayer<MobileSubstrate> *self, SEL sel, CGSize size) {
25f84761
JF
141 self = [self ms$initWithSize:size];
142 if (self == nil)
143 return nil;
39f17851 144 [self setBackgroundColor:[UIColor darkGrayColor]];
25f84761
JF
145 return self;
146}
147
dbbe0f32
JF
148/*MSHook(void, SBSlidingAlertDisplay$updateDesktopImage$, SBSlidingAlertDisplay *self, SEL sel, UIImage *image) {
149 NSString *text(@"\"Sad iPhone\" by Geoff Stearns");
150 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
151 if (_backgroundView != nil)
152 text = nil;
153 _SBSlidingAlertDisplay$updateDesktopImage$(self, sel, image);
154 if (text != nil) {
155 UIFont *font([UIFont systemFontOfSize:12]);
156 CGRect rect([self frame]);
157 CGSize size([text sizeWithFont:font]);
158 rect.origin.y = 385 - 3 - 14;//size.height;
159 rect.size.height = size.height;
160
161 UITextView *view([[UITextView alloc] initWithFrame:rect]);
162 [view setTextAlignment:UITextAlignmentCenter];
163 [view setMarginTop:0];
164 [view setFont:font];
165 [view setText:text];
166 [view setTextColor:[UIColor grayColor]];
167 [view setBackgroundColor:[UIColor clearColor]];
168
169 [self insertSubview:view aboveSubview:_backgroundView];
170 }
171}*/
172
173#define Paper_ "/Library/MobileSubstrate/MobilePaper.png"
174
175MSHook(UIImage *, UIImage$defaultDesktopImage, UIImage *self, SEL sel) {
176 return [UIImage imageWithContentsOfFile:@Paper_];
177}
178
39f17851
JF
179MSHook(void, SBStatusBarTimeView$tile, SBStatusBarTimeView *self, SEL sel) {
180 NSString *&_time(MSHookIvar<NSString *>(self, "_time"));
181 CGRect &_textRect(MSHookIvar<CGRect>(self, "_textRect"));
25f84761 182 if (_time != nil)
39f17851 183 [_time release];
dbbe0f32 184 _time = [@"Exit Safe Mode" retain];
39f17851
JF
185 GSFontRef font([self textFont]);
186 CGSize size([_time sizeWithFont:(id)font]);
187 CGRect frame([self frame]);
39f17851
JF
188 _textRect.size = size;
189 _textRect.origin.x = (frame.size.width - size.width) / 2;
190 _textRect.origin.y = (frame.size.height - size.height) / 2;
25f84761
JF
191}
192
193#define Dylib_ "/Library/MobileSubstrate/MobileSubstrate.dylib"
194
39f17851 195extern "C" void MSInitialize() {
25f84761
JF
196 NSLog(@"MS:Warning: Entering Safe Mode");
197
198 MSHookMessage(objc_getClass("SBButtonBar"), @selector(maxIconColumns), (IMP) &SBButtonBar$maxIconColumns, "ms$");
199 MSHookMessage(objc_getClass("SBContentLayer"), @selector(initWithSize:), (IMP) &SBContentLayer$initWithSize$, "ms$");
39f17851
JF
200 _SBStatusBar$mouseDown$ = MSHookMessage(objc_getClass("SBStatusBar"), @selector(mouseDown:), &$SBStatusBar$mouseDown$);
201 _SBStatusBarTimeView$tile = MSHookMessage(objc_getClass("SBStatusBarTimeView"), @selector(tile), &$SBStatusBarTimeView$tile);
25f84761 202
dbbe0f32
JF
203 _UIImage$defaultDesktopImage = MSHookMessage(object_getClass(objc_getClass("UIImage")), @selector(defaultDesktopImage), &$UIImage$defaultDesktopImage);
204 //_SBSlidingAlertDisplay$updateDesktopImage$ = MSHookMessage(objc_getClass("SBSlidingAlertDisplay"), @selector(updateDesktopImage:), &$SBSlidingAlertDisplay$updateDesktopImage$);
205
25f84761
JF
206 char *dil = getenv("DYLD_INSERT_LIBRARIES");
207 if (dil == NULL)
208 NSLog(@"MS:Error: DYLD_INSERT_LIBRARIES is unset?");
209 else {
210 NSArray *dylibs([[NSString stringWithUTF8String:dil] componentsSeparatedByString:@":"]);
211 NSUInteger index([dylibs indexOfObject:@ Dylib_]);
212 if (index == NSNotFound)
213 NSLog(@"MS:Error: dylib not in DYLD_INSERT_LIBRARIES?");
214 else if ([dylibs count] == 1)
215 unsetenv("DYLD_INSERT_LIBRARIES");
216 else {
217 NSMutableArray *value([[[NSMutableArray alloc] init] autorelease]);
218 [value setArray:dylibs];
219 [value removeObjectAtIndex:index];
220 setenv("DYLD_INSERT_LIBRARIES", [[value componentsJoinedByString:@":"] UTF8String], !0);
221 }
222 }
223
39f17851
JF
224 $SBAlertItemsController = objc_getClass("SBAlertItemsController");
225
25f84761
JF
226 if (Class _class = objc_getClass("SBIconController")) {
227 SEL sel(@selector(showInfoAlertIfNeeded));
228 if (Method method = class_getInstanceMethod(_class, sel))
39f17851 229 method_setImplementation(method, (IMP) &SBIconController$showInfoAlertIfNeeded);
25f84761
JF
230 }
231}