]> git.saurik.com Git - safemode-ios.git/blame_incremental - MobileSafety.mm
Refactor SafeMode to a separate package.
[safemode-ios.git] / MobileSafety.mm
... / ...
CommitLineData
1/* Cydia Substrate - Powerful Code Insertion Platform
2 * Copyright (C) 2008-2011 Jay Freeman (saurik)
3*/
4
5/* GNU Lesser General Public License, Version 3 {{{ */
6/*
7 * Substrate 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.
11 *
12 * Substrate 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.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with Substrate. If not, see <http://www.gnu.org/licenses/>.
19**/
20/* }}} */
21
22%apt Package: com.saurik.substrate.safemode
23%apt Author: Jay Freeman (saurik) <saurik@saurik.com>
24
25%apt Name: Substrate Safe Mode
26%apt Description: safe mode safety extension (safe)
27
28%apt Depends: mobilesubstrate (>= 0.9.3367+38)
29
30%fflag 1
31%fflag 2
32
33%bundle com.apple.springboard
34
35%flag -framework Foundation
36%flag -framework UIKit
37
38#import <CoreFoundation/CoreFoundation.h>
39#import <Foundation/Foundation.h>
40#import <CoreGraphics/CGGeometry.h>
41#import <UIKit/UIKit.h>
42
43#include "CydiaSubstrate.h"
44
45MSClassHook(UIStatusBar)
46
47MSClassHook(UIImage)
48MSMetaClassHook(UIImage)
49
50MSClassHook(AAAccountManager)
51MSMetaClassHook(AAAccountManager)
52
53MSClassHook(SBAlertItemsController)
54MSClassHook(SBButtonBar)
55MSClassHook(SBIconController)
56MSClassHook(SBStatusBar)
57MSClassHook(SBStatusBarDataManager)
58MSClassHook(SBStatusBarTimeView)
59MSClassHook(SBUIController)
60
61Class $SafeModeAlertItem;
62
63@interface SBAlertItem : NSObject {
64}
65- (UIAlertView *) alertSheet;
66- (void) dismiss;
67@end
68
69@interface SBAlertItemsController : NSObject {
70}
71+ (SBAlertItemsController *) sharedInstance;
72- (void) activateAlertItem:(SBAlertItem *)item;
73@end
74
75@interface SBStatusBarTimeView : UIView {
76}
77- (id) textFont;
78@end
79
80@interface UIApplication (CydiaSubstrate)
81- (void) applicationOpenURL:(id)url;
82@end
83
84@interface UIAlertView (CydiaSubstrate)
85- (void) setForceHorizontalButtonsLayout:(BOOL)force;
86- (void) setBodyText:(NSString *)body;
87- (void) setNumberOfRows:(NSInteger)rows;
88@end
89
90void SafeModeAlertItem$alertSheet$buttonClicked$(id self, SEL sel, id sheet, int button) {
91 switch (button) {
92 case 1:
93 break;
94
95 case 2:
96 exit(0);
97 break;
98
99 case 3:
100 [[UIApplication sharedApplication] applicationOpenURL:[NSURL URLWithString:@"http://cydia.saurik.com/safemode/"]];
101 break;
102 }
103
104 [self dismiss];
105}
106
107void SafeModeAlertItem$configure$requirePasscodeForActions$(id self, SEL sel, BOOL configure, BOOL require) {
108 UIAlertView *sheet([self alertSheet]);
109 [sheet setDelegate:self];
110 [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.\n\nTap \"Help\" below for more tips."];
111 [sheet addButtonWithTitle:@"OK"];
112 [sheet addButtonWithTitle:@"Restart"];
113 [sheet addButtonWithTitle:@"Help"];
114 [sheet setNumberOfRows:1];
115 if ([sheet respondsToSelector:@selector(setForceHorizontalButtonsLayout:)])
116 [sheet setForceHorizontalButtonsLayout:YES];
117}
118
119void SafeModeAlertItem$performUnlockAction(id self, SEL sel) {
120 [[$SBAlertItemsController sharedInstance] activateAlertItem:self];
121}
122
123static void MSAlert() {
124 if ($SafeModeAlertItem == nil)
125 $SafeModeAlertItem = objc_lookUpClass("SafeModeAlertItem");
126 if ($SafeModeAlertItem == nil) {
127 $SafeModeAlertItem = objc_allocateClassPair(objc_getClass("SBAlertItem"), "SafeModeAlertItem", 0);
128 if ($SafeModeAlertItem == nil)
129 return;
130
131 class_addMethod($SafeModeAlertItem, @selector(alertSheet:buttonClicked:), (IMP) &SafeModeAlertItem$alertSheet$buttonClicked$, "v@:@i");
132 class_addMethod($SafeModeAlertItem, @selector(configure:requirePasscodeForActions:), (IMP) &SafeModeAlertItem$configure$requirePasscodeForActions$, "v@:cc");
133 class_addMethod($SafeModeAlertItem, @selector(performUnlockAction), (IMP) SafeModeAlertItem$performUnlockAction, "v@:");
134 objc_registerClassPair($SafeModeAlertItem);
135 }
136
137 if ($SBAlertItemsController != nil)
138 [[$SBAlertItemsController sharedInstance] activateAlertItem:[[[$SafeModeAlertItem alloc] init] autorelease]];
139}
140
141MSInstanceMessageHook2(void, SBStatusBar, touchesEnded,withEvent, id, touches, id, event) {
142 MSAlert();
143 MSOldCall(touches, event);
144}
145
146MSInstanceMessageHook1(void, SBStatusBar, mouseDown, void *, event) {
147 MSAlert();
148 MSOldCall(event);
149}
150
151MSInstanceMessageHook2(void, UIStatusBar, touchesBegan,withEvent, void *, touches, void *, event) {
152 MSAlert();
153 MSOldCall(touches, event);
154}
155
156MSInstanceMessageHook0(void, SBStatusBarDataManager, _updateTimeString) {
157 char *_data(&MSHookIvar<char>(self, "_data"));
158 if (_data == NULL)
159 return;
160
161 Ivar _itemIsEnabled(object_getInstanceVariable(self, "_itemIsEnabled", NULL));
162 if (_itemIsEnabled == NULL)
163 return;
164
165 Ivar _itemIsCloaked(object_getInstanceVariable(self, "_itemIsCloaked", NULL));
166 if (_itemIsCloaked == NULL)
167 return;
168
169 size_t enabledOffset(ivar_getOffset(_itemIsEnabled));
170 size_t cloakedOffset(ivar_getOffset(_itemIsCloaked));
171 if (enabledOffset >= cloakedOffset)
172 return;
173
174 size_t offset(cloakedOffset - enabledOffset);
175 char *timeString(_data + offset);
176 strcpy(timeString, "Exit Safe Mode");
177}
178
179static bool alerted_;
180
181static void AlertIfNeeded() {
182 if (alerted_)
183 return;
184 alerted_ = true;
185 MSAlert();
186}
187
188MSClassMessageHook0(void, AAAccountManager, showMobileMeOfferIfNecessary) {
189 AlertIfNeeded();
190}
191
192MSInstanceMessageHook0(void, SBIconController, showInfoAlertIfNeeded) {
193 AlertIfNeeded();
194}
195
196MSInstanceMessageHook0(int, SBButtonBar, maxIconColumns) {
197 static int max;
198 if (max == 0) {
199 max = MSOldCall();
200 if (NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults])
201 if (NSDictionary *iconState = [defaults objectForKey:@"iconState"])
202 if (NSDictionary *buttonBar = [iconState objectForKey:@"buttonBar"])
203 if (NSArray *iconMatrix = [buttonBar objectForKey:@"iconMatrix"])
204 if ([iconMatrix count] != 0)
205 if (NSArray *row = [iconMatrix objectAtIndex:0]) {
206 int count([row count]);
207 if (max < count)
208 max = count;
209 }
210 } return max;
211}
212
213MSInstanceMessageHook0(id, SBUIController, init) {
214 if ((self = MSOldCall()) != nil) {
215 UIView *&_contentLayer(MSHookIvar<UIView *>(self, "_contentLayer"));
216 UIView *&_contentView(MSHookIvar<UIView *>(self, "_contentView"));
217
218 UIView *layer;
219 if (&_contentLayer != NULL)
220 layer = _contentLayer;
221 else if (&_contentView != NULL)
222 layer = _contentView;
223 else
224 layer = nil;
225
226 if (layer != nil)
227 [layer setBackgroundColor:[UIColor darkGrayColor]];
228 } return self;
229}
230
231#define Paper_ "/Library/MobileSubstrate/MobileSafety.png"
232
233MSClassMessageHook0(UIImage *, UIImage, defaultDesktopImage) {
234 return [UIImage imageWithContentsOfFile:@Paper_];
235}
236
237MSInstanceMessageHook0(void, SBStatusBarTimeView, tile) {
238 NSString *&_time(MSHookIvar<NSString *>(self, "_time"));
239 CGRect &_textRect(MSHookIvar<CGRect>(self, "_textRect"));
240 if (_time != nil)
241 [_time release];
242 _time = [@"Exit Safe Mode" retain];
243 id font([self textFont]);
244 CGSize size([_time sizeWithFont:font]);
245 CGRect frame([self frame]);
246 _textRect.size = size;
247 _textRect.origin.x = (frame.size.width - size.width) / 2;
248 _textRect.origin.y = (frame.size.height - size.height) / 2;
249}