/* Cydia - iPhone UIKit Front-End for Debian APT
* Copyright (C) 2008-2015 Jay Freeman (saurik)
*/
/* GNU General Public License, Version 3 {{{ */
/*
* Cydia is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* Cydia is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Cydia. If not, see .
**/
/* }}} */
#include "CyteKit/UCPlatform.h"
#include
#include
#include
#include
#include "CyteKit/CyteObject.h"
#include "CyteKit/WebViewController.h"
#include "CyteKit/countByEnumeratingWithState.h"
#include "CyteKit/extern.h"
#include "iPhonePrivate.h"
#include
@implementation NSDictionary (Cydia)
- (id) invokeUndefinedMethodFromWebScript:(NSString *)name withArguments:(NSArray *)arguments {
if (false);
else if ([name isEqualToString:@"get"])
return [self objectForKey:[arguments objectAtIndex:0]];
else if ([name isEqualToString:@"keys"])
return [self allKeys];
return nil;
} @end
static NSString *CYHex(NSData *data, bool reverse = false) {
if (data == nil)
return nil;
size_t length([data length]);
uint8_t bytes[length];
[data getBytes:bytes];
char string[length * 2 + 1];
for (size_t i(0); i != length; ++i)
sprintf(string + i * 2, "%.2x", bytes[reverse ? length - i - 1 : i]);
return [NSString stringWithUTF8String:string];
}
static NSObject *CYIOGetValue(const char *path, NSString *property) {
io_registry_entry_t entry(IORegistryEntryFromPath(kIOMasterPortDefault, path));
if (entry == MACH_PORT_NULL)
return nil;
CFTypeRef value(IORegistryEntryCreateCFProperty(entry, (CFStringRef) property, kCFAllocatorDefault, 0));
IOObjectRelease(entry);
if (value == NULL)
return nil;
return [(id) value autorelease];
}
@implementation CyteObject {
_H indirect_;
}
+ (BOOL) isKeyExcludedFromWebScript:(const char *)name {
return false;
}
- (id) initWithDelegate:(CyteWebViewController *)indirect {
if ((self = [super init]) != nil) {
indirect_ = indirect;
} return self;
}
- (NSArray *) attributeKeys {
return [NSArray arrayWithObjects:
@"bbsnum",
@"bittage",
@"build",
@"coreFoundationVersionNumber",
@"ecid",
@"firmware",
@"hostname",
@"idiom",
@"model",
@"serial",
nil];
}
- (unsigned) bittage {
#if 0
#elif defined(__arm64__)
return 64;
#elif defined(__arm__)
return 32;
#else
return 0;
#endif
}
- (NSString *) bbsnum {
return (id) CYHex((NSData *) CYIOGetValue("IOService:/AppleARMPE/baseband", @"snum"), false) ?: [NSNull null];
}
- (NSString *) build {
return [NSString stringWithUTF8String:System_];
}
- (NSString *) coreFoundationVersionNumber {
return [NSString stringWithFormat:@"%.2f", kCFCoreFoundationVersionNumber];
}
- (NSString *) ecid {
return (id) [CYHex((NSData *) CYIOGetValue("IODeviceTree:/chosen", @"unique-chip-id"), true) uppercaseString] ?: [NSNull null];
}
- (NSString *) firmware {
return [[UIDevice currentDevice] systemVersion];
}
- (NSString *) hostname {
return [[UIDevice currentDevice] name];
}
- (NSString *) idiom {
return IsWildcat_ ? @"ipad" : @"iphone";
}
- (NSString *) model {
return [NSString stringWithUTF8String:Machine_];
}
- (NSString *) serial {
return (NSString *) CYIOGetValue("IOService:/", @"IOPlatformSerialNumber");
}
+ (NSString *) webScriptNameForSelector:(SEL)selector {
if (false);
else if (selector == @selector(addInternalRedirect::))
return @"addInternalRedirect";
else if (selector == @selector(close))
return @"close";
else if (selector == @selector(stringWithFormat:arguments:))
return @"format";
else if (selector == @selector(getIORegistryEntry::))
return @"getIORegistryEntry";
else if (selector == @selector(getKernelNumber:))
return @"getKernelNumber";
else if (selector == @selector(getKernelString:))
return @"getKernelString";
else if (selector == @selector(getLocaleIdentifier))
return @"getLocaleIdentifier";
else if (selector == @selector(getPreferredLanguages))
return @"getPreferredLanguages";
else if (selector == @selector(isReachable:))
return @"isReachable";
else if (selector == @selector(localizedStringForKey:value:table:))
return @"localize";
else if (selector == @selector(popViewController:))
return @"popViewController";
else if (selector == @selector(registerFrame:))
return @"registerFrame";
else if (selector == @selector(removeButton))
return @"removeButton";
else if (selector == @selector(scrollToBottom:))
return @"scrollToBottom";
else if (selector == @selector(setAllowsNavigationAction:))
return @"setAllowsNavigationAction";
else if (selector == @selector(setBadgeValue:))
return @"setBadgeValue";
else if (selector == @selector(setButtonImage:withStyle:toFunction:))
return @"setButtonImage";
else if (selector == @selector(setButtonTitle:withStyle:toFunction:))
return @"setButtonTitle";
else if (selector == @selector(setHidesBackButton:))
return @"setHidesBackButton";
else if (selector == @selector(setHidesNavigationBar:))
return @"setHidesNavigationBar";
else if (selector == @selector(setNavigationBarStyle:))
return @"setNavigationBarStyle";
else if (selector == @selector(setNavigationBarTintRed:green:blue:alpha:))
return @"setNavigationBarTintColor";
else if (selector == @selector(setPasteboardString:))
return @"setPasteboardString";
else if (selector == @selector(setPasteboardURL:))
return @"setPasteboardURL";
else if (selector == @selector(setScrollAlwaysBounceVertical:))
return @"setScrollAlwaysBounceVertical";
else if (selector == @selector(setScrollIndicatorStyle:))
return @"setScrollIndicatorStyle";
else if (selector == @selector(setViewportWidth:))
return @"setViewportWidth";
else if (selector == @selector(statfs:))
return @"statfs";
else if (selector == @selector(supports:))
return @"supports";
else if (selector == @selector(unload))
return @"unload";
else
return nil;
}
+ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector {
return [self webScriptNameForSelector:selector] == nil;
}
- (void) addInternalRedirect:(NSString *)from :(NSString *)to {
[CyteWebViewController performSelectorOnMainThread:@selector(addDiversion:) withObject:[[[Diversion alloc] initWithFrom:from to:to] autorelease] waitUntilDone:NO];
}
- (void) close {
[indirect_ performSelectorOnMainThread:@selector(close) withObject:nil waitUntilDone:NO];
}
- (NSString *) getKernelString:(NSString *)name {
const char *string([name UTF8String]);
size_t size;
if (sysctlbyname(string, NULL, &size, NULL, 0) == -1)
return (id) [NSNull null];
char value[size + 1];
if (sysctlbyname(string, value, &size, NULL, 0) == -1)
return (id) [NSNull null];
// XXX: just in case you request something ludicrous
value[size] = '\0';
return [NSString stringWithCString:value];
}
- (NSObject *) getIORegistryEntry:(NSString *)path :(NSString *)entry {
NSObject *value(CYIOGetValue([path UTF8String], entry));
if (value != nil)
if ([value isKindOfClass:[NSData class]])
value = CYHex((NSData *) value);
return value;
}
- (NSString *) getLocaleIdentifier {
_H locale(CFLocaleCopyCurrent(), true);
return locale == NULL ? (NSString *) [NSNull null] : (NSString *) CFLocaleGetIdentifier(locale);
}
- (NSArray *) getPreferredLanguages {
return [NSLocale preferredLanguages];
}
- (NSNumber *) isReachable:(NSString *)name {
return [NSNumber numberWithBool:CyteIsReachable([name UTF8String])];
}
- (NSString *) localizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)table {
if (reinterpret_cast(value) == [WebUndefined undefined])
value = nil;
if (reinterpret_cast(table) == [WebUndefined undefined])
table = nil;
return [[NSBundle mainBundle] localizedStringForKey:key value:value table:table];
}
- (void) popViewController:(NSNumber *)value {
if (value == (id) [WebUndefined undefined])
value = [NSNumber numberWithBool:YES];
[indirect_ performSelectorOnMainThread:@selector(popViewControllerWithNumber:) withObject:value waitUntilDone:NO];
}
- (void) registerFrame:(DOMHTMLIFrameElement *)iframe {
WebFrame *frame([iframe contentFrame]);
[indirect_ registerFrame:frame];
}
- (void) removeButton {
[indirect_ removeButton];
}
- (void) scrollToBottom:(NSNumber *)animated {
[indirect_ performSelectorOnMainThread:@selector(scrollToBottomAnimated:) withObject:animated waitUntilDone:NO];
}
- (void) setAllowsNavigationAction:(NSString *)value {
[indirect_ performSelectorOnMainThread:@selector(setAllowsNavigationActionByNumber:) withObject:value waitUntilDone:NO];
}
- (void) setBadgeValue:(id)value {
[indirect_ performSelectorOnMainThread:@selector(setBadgeValue:) withObject:value waitUntilDone:NO];
}
- (void) setButtonImage:(NSString *)button withStyle:(NSString *)style toFunction:(id)function {
[indirect_ setButtonImage:button withStyle:style toFunction:function];
}
- (void) setButtonTitle:(NSString *)button withStyle:(NSString *)style toFunction:(id)function {
[indirect_ setButtonTitle:button withStyle:style toFunction:function];
}
- (void) setHidesBackButton:(NSString *)value {
[indirect_ performSelectorOnMainThread:@selector(setHidesBackButtonByNumber:) withObject:value waitUntilDone:NO];
}
- (void) setHidesNavigationBar:(NSString *)value {
[indirect_ performSelectorOnMainThread:@selector(setHidesNavigationBarByNumber:) withObject:value waitUntilDone:NO];
}
- (void) setNavigationBarStyle:(NSString *)value {
[indirect_ performSelectorOnMainThread:@selector(setNavigationBarStyle:) withObject:value waitUntilDone:NO];
}
- (void) setNavigationBarTintRed:(NSNumber *)red green:(NSNumber *)green blue:(NSNumber *)blue alpha:(NSNumber *)alpha {
float opacity(alpha == (id) [WebUndefined undefined] ? 1 : [alpha floatValue]);
UIColor *color([UIColor colorWithRed:[red floatValue] green:[green floatValue] blue:[blue floatValue] alpha:opacity]);
[indirect_ performSelectorOnMainThread:@selector(setNavigationBarTintColor:) withObject:color waitUntilDone:NO];
}
- (void) setPasteboardString:(NSString *)value {
[[objc_getClass("UIPasteboard") generalPasteboard] setString:value];
}
- (void) setPasteboardURL:(NSString *)value {
[[objc_getClass("UIPasteboard") generalPasteboard] setURL:[NSURL URLWithString:value]];
}
- (void) setScrollAlwaysBounceVertical:(NSNumber *)value {
[indirect_ performSelectorOnMainThread:@selector(setScrollAlwaysBounceVerticalNumber:) withObject:value waitUntilDone:NO];
}
- (void) setScrollIndicatorStyle:(NSString *)style {
[indirect_ performSelectorOnMainThread:@selector(setScrollIndicatorStyleWithName:) withObject:style waitUntilDone:NO];
}
- (void) setViewportWidth:(float)width {
[indirect_ setViewportWidthOnMainThread:width];
}
- (NSArray *) statfs:(NSString *)path {
struct statfs stat;
if (path == nil || statfs([path UTF8String], &stat) == -1)
return nil;
return [NSArray arrayWithObjects:
[NSNumber numberWithUnsignedLong:stat.f_bsize],
[NSNumber numberWithUnsignedLong:stat.f_blocks],
[NSNumber numberWithUnsignedLong:stat.f_bfree],
nil];
}
- (NSString *) stringWithFormat:(NSString *)format arguments:(WebScriptObject *)arguments {
//NSLog(@"SWF:\"%@\" A:%@", format, [arguments description]);
unsigned count([arguments count]);
id values[count];
for (unsigned i(0); i != count; ++i)
values[i] = [arguments objectAtIndex:i];
return [[[NSString alloc] initWithFormat:format arguments:reinterpret_cast(values)] autorelease];
}
- (BOOL) supports:(NSString *)feature {
return [feature isEqualToString:@"window.open"];
}
- (void) unload {
[[indirect_ rootViewController] performSelectorOnMainThread:@selector(unloadData) withObject:nil waitUntilDone:NO];
}
@end