1 /* Cydia Substrate - Powerful Code Insertion Platform
2 * Copyright (C) 2008-2011 Jay Freeman (saurik)
5 /* GNU Lesser General Public License, Version 3 {{{ */
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.
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.
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/>.
22 %apt Package: com.saurik.substrate.safemode
23 %apt Author: Jay Freeman (saurik) <saurik@saurik.com>
25 %apt Name: Substrate Safe Mode
26 %apt Description: safe mode safety extension (safe)
28 %apt Depends: mobilesubstrate (>= 0.9.3367+38)
33 %bundle com.apple.springboard
35 %flag -framework Foundation
36 %flag -framework UIKit
38 #import <CoreFoundation/CoreFoundation.h>
39 #import <Foundation/Foundation.h>
40 #import <CoreGraphics/CGGeometry.h>
41 #import <UIKit/UIKit.h>
43 #include "CydiaSubstrate.h"
45 MSClassHook(UIStatusBar)
48 MSMetaClassHook(UIImage)
50 MSClassHook(AAAccountManager)
51 MSMetaClassHook(AAAccountManager)
53 MSClassHook(SBAlertItemsController)
54 MSClassHook(SBButtonBar)
55 MSClassHook(SBIconController)
56 MSClassHook(SBStatusBar)
57 MSClassHook(SBStatusBarDataManager)
58 MSClassHook(SBStatusBarTimeView)
59 MSClassHook(SBUIController)
61 Class $SafeModeAlertItem;
63 @interface SBAlertItem : NSObject {
65 - (UIAlertView *) alertSheet;
69 @interface SBAlertItemsController : NSObject {
71 + (SBAlertItemsController *) sharedInstance;
72 - (void) activateAlertItem:(SBAlertItem *)item;
75 @interface SBStatusBarTimeView : UIView {
80 @interface UIApplication (CydiaSubstrate)
81 - (void) applicationOpenURL:(id)url;
84 @interface UIAlertView (CydiaSubstrate)
85 - (void) setForceHorizontalButtonsLayout:(BOOL)force;
86 - (void) setBodyText:(NSString *)body;
87 - (void) setNumberOfRows:(NSInteger)rows;
90 void SafeModeAlertItem$alertSheet$buttonClicked$(id self, SEL sel, id sheet, int button) {
100 [[UIApplication sharedApplication] applicationOpenURL:[NSURL URLWithString:@"http://cydia.saurik.com/safemode/"]];
107 void 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];
119 void SafeModeAlertItem$performUnlockAction(id self, SEL sel) {
120 [[$SBAlertItemsController sharedInstance] activateAlertItem:self];
123 static 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)
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);
137 if ($SBAlertItemsController != nil)
138 [[$SBAlertItemsController sharedInstance] activateAlertItem:[[[$SafeModeAlertItem alloc] init] autorelease]];
141 MSInstanceMessageHook2(void, SBStatusBar, touchesEnded,withEvent, id, touches, id, event) {
143 MSOldCall(touches, event);
146 MSInstanceMessageHook1(void, SBStatusBar, mouseDown, void *, event) {
151 MSInstanceMessageHook2(void, UIStatusBar, touchesBegan,withEvent, void *, touches, void *, event) {
153 MSOldCall(touches, event);
156 MSInstanceMessageHook0(void, SBStatusBarDataManager, _updateTimeString) {
157 char *_data(&MSHookIvar<char>(self, "_data"));
161 Ivar _itemIsEnabled(object_getInstanceVariable(self, "_itemIsEnabled", NULL));
162 if (_itemIsEnabled == NULL)
165 Ivar _itemIsCloaked(object_getInstanceVariable(self, "_itemIsCloaked", NULL));
166 if (_itemIsCloaked == NULL)
169 size_t enabledOffset(ivar_getOffset(_itemIsEnabled));
170 size_t cloakedOffset(ivar_getOffset(_itemIsCloaked));
171 if (enabledOffset >= cloakedOffset)
174 size_t offset(cloakedOffset - enabledOffset);
175 char *timeString(_data + offset);
176 strcpy(timeString, "Exit Safe Mode");
179 static bool alerted_;
181 static void AlertIfNeeded() {
188 MSClassMessageHook0(void, AAAccountManager, showMobileMeOfferIfNecessary) {
192 MSInstanceMessageHook0(void, SBIconController, showInfoAlertIfNeeded) {
196 MSInstanceMessageHook0(int, SBButtonBar, maxIconColumns) {
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]);
213 MSInstanceMessageHook0(id, SBUIController, init) {
214 if ((self = MSOldCall()) != nil) {
215 UIView *&_contentLayer(MSHookIvar<UIView *>(self, "_contentLayer"));
216 UIView *&_contentView(MSHookIvar<UIView *>(self, "_contentView"));
219 if (&_contentLayer != NULL)
220 layer = _contentLayer;
221 else if (&_contentView != NULL)
222 layer = _contentView;
227 [layer setBackgroundColor:[UIColor darkGrayColor]];
231 #define Paper_ "/Library/MobileSubstrate/MobileSafety.png"
233 MSClassMessageHook0(UIImage *, UIImage, defaultDesktopImage) {
234 return [UIImage imageWithContentsOfFile:@Paper_];
237 MSInstanceMessageHook0(void, SBStatusBarTimeView, tile) {
238 NSString *&_time(MSHookIvar<NSString *>(self, "_time"));
239 CGRect &_textRect(MSHookIvar<CGRect>(self, "_textRect"));
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;