mirror of
https://github.com/danog/Telegram.git
synced 2024-12-02 09:27:55 +01:00
294 lines
6.8 KiB
Objective-C
294 lines
6.8 KiB
Objective-C
/*
|
|
* This is the source code of Telegram for iOS v. 1.1
|
|
* It is licensed under GNU GPL v. 2 or later.
|
|
* You should have received a copy of the license in this archive (see LICENSE).
|
|
*
|
|
* Copyright Ernesto Guevara, 2014.
|
|
*/
|
|
|
|
#import "FreedomUIKit.h"
|
|
|
|
#import <objc/runtime.h>
|
|
#import <objc/message.h>
|
|
|
|
#import "TGHacks.h"
|
|
#import "TGNavigationController.h"
|
|
|
|
#define DEBUG_KEYBOARD_QUEUE false
|
|
|
|
void freedomUIKitInit2(); // iOS 6
|
|
void freedomUIKitInit3(); // Notification Center Hook
|
|
|
|
#if defined(DEBUG) && DEBUG_KEYBOARD_QUEUE
|
|
void freedomUIKitInit4(); // Keyboard Queue Debug
|
|
#endif
|
|
|
|
void freedomUIKitInit()
|
|
{
|
|
freedomUIKitInit2();
|
|
freedomUIKitInit3();
|
|
|
|
#if defined(DEBUG) && DEBUG_KEYBOARD_QUEUE
|
|
freedomUIKitInit4();
|
|
#endif
|
|
}
|
|
|
|
#pragma mark -
|
|
|
|
static int freedomUIKit_decorated2(__unused id self, __unused SEL _cmd)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
void freedomUIKitInit2()
|
|
{
|
|
if (iosMajorVersion() == 6)
|
|
{
|
|
FreedomDecoration instanceDecorations[] = {
|
|
{ .name = 0,
|
|
.imp = (IMP)&freedomUIKit_decorated2,
|
|
.newIdentifier = (FreedomIdentifier){ .string = "3066a13b3e6b", .key = 0x52d50551U },
|
|
.newEncoding = (FreedomIdentifier){ .string = "1a7291", .key = 0x3ab3273U }
|
|
}
|
|
};
|
|
|
|
freedomClassAutoDecorate(0x1468e61aU, NULL, 0, instanceDecorations, sizeof(instanceDecorations) / sizeof(instanceDecorations[0]));
|
|
}
|
|
}
|
|
|
|
#pragma mark -
|
|
|
|
static bool test3 = false;
|
|
static bool test3_1 = false;
|
|
|
|
@implementation FFNotificationCenter
|
|
|
|
static bool (^shouldRotateBlock)() = nil;
|
|
|
|
+ (void)setShouldRotateBlock:(bool (^)())block
|
|
{
|
|
shouldRotateBlock = [block copy];
|
|
}
|
|
|
|
- (void)postNotificationName:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo
|
|
{
|
|
bool clearFlag = false;
|
|
if ([aName isEqualToString:UIDeviceOrientationDidChangeNotification])
|
|
{
|
|
clearFlag = true;
|
|
test3 = true;
|
|
test3_1 = true;
|
|
}
|
|
|
|
if ([aName isEqualToString:UIDeviceOrientationDidChangeNotification])
|
|
{
|
|
if (shouldRotateBlock == nil || shouldRotateBlock())
|
|
[super postNotificationName:aName object:anObject userInfo:aUserInfo];
|
|
}
|
|
else
|
|
[super postNotificationName:aName object:anObject userInfo:aUserInfo];
|
|
|
|
if (clearFlag)
|
|
test3 = false;
|
|
}
|
|
|
|
@end
|
|
|
|
bool freedomUIKitTest3()
|
|
{
|
|
return test3;
|
|
}
|
|
|
|
bool freedomUIKitTest3_1()
|
|
{
|
|
bool value = test3_1;
|
|
test3_1 = false;
|
|
return value;
|
|
}
|
|
|
|
void freedomUIKitInit3()
|
|
{
|
|
object_setClass([NSNotificationCenter defaultCenter], [FFNotificationCenter class]);
|
|
}
|
|
|
|
#pragma mark -
|
|
|
|
static bool test4 = false;
|
|
static bool test4_1 = false;
|
|
|
|
@interface TGHelperQueue : NSProxy
|
|
{
|
|
id _target;
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation TGHelperQueue
|
|
|
|
- (instancetype)initWithTargetQueue:(id)target
|
|
{
|
|
if (self != nil)
|
|
{
|
|
_target = target;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
|
|
{
|
|
return [_target methodSignatureForSelector:selector];
|
|
}
|
|
|
|
- (void)forwardInvocation:(NSInvocation *)__unused invocation
|
|
{
|
|
}
|
|
|
|
- (id)forwardingTargetForSelector:(SEL)selector
|
|
{
|
|
static char *name = NULL;
|
|
static dispatch_once_t onceToken;
|
|
dispatch_once(&onceToken, ^
|
|
{
|
|
name = copyFreedomIdentifierValue((FreedomIdentifier){ .string = "536772a971686fb4484777b1706768b6574769b8626f75b4576e7eb9", .key = 0xdd1b0624U });
|
|
});
|
|
|
|
if (!strcmp(sel_getName(selector), name))
|
|
{
|
|
if (test4 || test4_1)
|
|
{
|
|
return nil;
|
|
}
|
|
}
|
|
|
|
return _target;
|
|
}
|
|
|
|
- (void)doWork
|
|
{
|
|
}
|
|
|
|
@end
|
|
|
|
static UIView *freedomUIKitFindView(UIView *view)
|
|
{
|
|
if (view == nil)
|
|
return nil;
|
|
|
|
if (object_getClass(view) == freedomClass(0x9cb128e7U))
|
|
return view;
|
|
|
|
for (UIView *subview in view.subviews)
|
|
{
|
|
UIView *result = freedomUIKitFindView(subview);
|
|
if (result != nil)
|
|
return result;
|
|
}
|
|
|
|
return nil;
|
|
}
|
|
|
|
void freedomUIKitTest4(dispatch_block_t block)
|
|
{
|
|
if (iosMajorVersion() < 7 || iosMajorVersion() > 7 || (iosMajorVersion() == 7 && iosMinorVersion() >= 1))
|
|
{
|
|
if (block != nil)
|
|
block();
|
|
}
|
|
else
|
|
{
|
|
UIView *view = freedomUIKitFindView([TGHacks applicationKeyboardWindow]);
|
|
if (view != nil)
|
|
{
|
|
static ptrdiff_t queueOffset = -1;
|
|
static bool queueInitialized = false;
|
|
if (!queueInitialized)
|
|
{
|
|
queueInitialized = true;
|
|
queueOffset = freedomIvarOffset(object_getClass(view), 0xba913cbU);
|
|
}
|
|
|
|
if (queueOffset >= 0)
|
|
{
|
|
__strong NSObject **queue = ((__strong NSObject **)(void *)(((uint8_t *)(__bridge void *)view) + queueOffset));
|
|
if (*queue != nil)
|
|
{
|
|
if (object_getClass(*queue) != [TGHelperQueue class])
|
|
{
|
|
TGHelperQueue *helper = [[TGHelperQueue alloc] initWithTargetQueue:*queue];
|
|
*queue = (NSObject *)helper;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool previousTest4 = test4;
|
|
test4 = true;
|
|
|
|
if (block != nil)
|
|
block();
|
|
|
|
test4 = previousTest4;
|
|
}
|
|
}
|
|
|
|
void freedomUIKitTest4_1()
|
|
{
|
|
test4_1 = true;
|
|
|
|
dispatch_async(dispatch_get_main_queue(), ^
|
|
{
|
|
test4_1 = false;
|
|
});
|
|
}
|
|
|
|
#if defined(DEBUG) && DEBUG_KEYBOARD_QUEUE
|
|
void freedomUIKit_decorated4_1(id self, SEL _cmd, id arg1)
|
|
{
|
|
static void (*nativeImpl)(id, SEL, id) = NULL;
|
|
static dispatch_once_t onceToken;
|
|
dispatch_once(&onceToken, ^
|
|
{
|
|
nativeImpl = (void *)freedomNativeImpl([self class], _cmd);
|
|
});
|
|
|
|
if (nativeImpl != NULL)
|
|
nativeImpl(self, _cmd, arg1);
|
|
|
|
TGLog(@"invoke %@", NSStringFromSelector(_cmd));
|
|
}
|
|
|
|
|
|
void freedomUIKit_decorated4_2(id self, SEL _cmd)
|
|
{
|
|
static void (*nativeImpl)(id, SEL) = NULL;
|
|
static dispatch_once_t onceToken;
|
|
dispatch_once(&onceToken, ^
|
|
{
|
|
nativeImpl = (void *)freedomNativeImpl([self class], _cmd);
|
|
});
|
|
|
|
if (nativeImpl != NULL)
|
|
nativeImpl(self, _cmd);
|
|
|
|
TGLog(@"invoke %@", NSStringFromSelector(_cmd));
|
|
}
|
|
|
|
void freedomUIKitInit4()
|
|
{
|
|
FreedomDecoration instanceDecorations[] = {
|
|
{ .name = 0xbb6dbb9eU, //addTask:
|
|
.imp = (IMP)&freedomUIKit_decorated4_1,
|
|
.newIdentifier = FreedomIdentifierEmpty,
|
|
.newEncoding = FreedomIdentifierEmpty
|
|
},
|
|
{ .name = 0x757d9b1cU, //waitUntilAllTasksAreFinished
|
|
.imp = (IMP)&freedomUIKit_decorated4_2,
|
|
.newIdentifier = FreedomIdentifierEmpty,
|
|
.newEncoding = FreedomIdentifierEmpty
|
|
}
|
|
};
|
|
|
|
freedomClassAutoDecorate(0xfed2643dU, NULL, 0, instanceDecorations, sizeof(instanceDecorations) / sizeof(instanceDecorations[0]));
|
|
}
|
|
#endif
|