X-Git-Url: https://git.saurik.com/cycript.git/blobdiff_plain/cbaa5f0fca8e863a2ba44bccbc27f09e5753980e..0df8d36b9315290aa2be056b1f9f945108332ce9:/Library.mm diff --git a/Library.mm b/Library.mm index b05138a..bb76f49 100644 --- a/Library.mm +++ b/Library.mm @@ -1,4 +1,4 @@ -/* Cycript - Remove Execution Server and Disassembler +/* Cycript - Remote Execution Server and Disassembler * Copyright (C) 2009 Jay Freeman (saurik) */ @@ -50,12 +50,11 @@ #include #include #include +#include #endif #include -#include - #include #include @@ -80,7 +79,7 @@ } while (false) #define _trace() do { \ - CFLog(kCFLogLevelNotice, CFSTR("_trace():%u"), __LINE__); \ + fprintf(stderr, "_trace():%u\n", __LINE__); \ } while (false) #define CYPoolTry { \ @@ -201,12 +200,52 @@ class CYJSString { } }; /* }}} */ +/* C Strings {{{ */ +// XXX: this macro is unhygenic +#define CYCastCString_(string) ({ \ + char *utf8; \ + if (string == NULL) \ + utf8 = NULL; \ + else { \ + size_t size(JSStringGetMaximumUTF8CStringSize(string)); \ + utf8 = reinterpret_cast(alloca(size)); \ + JSStringGetUTF8CString(string, utf8, size); \ + } \ + utf8; \ +}) + +// XXX: this macro is unhygenic +#define CYCastCString(context, value) ({ \ + char *utf8; \ + if (value == NULL) \ + utf8 = NULL; \ + else if (JSStringRef string = CYCopyJSString(context, value)) { \ + utf8 = CYCastCString_(string); \ + JSStringRelease(string); \ + } else \ + utf8 = NULL; \ + utf8; \ +}) +/* }}} */ /* Objective-C Strings {{{ */ +const char *CYPoolCString(apr_pool_t *pool, NSString *value) { + if (pool == NULL) + return [value UTF8String]; + else { + size_t size([value maximumLengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 1); + char *string(new(pool) char[size]); + if (![value getCString:string maxLength:size encoding:NSUTF8StringEncoding]) + @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"[NSString getCString:maxLength:encoding:] == NO" userInfo:nil]; + return string; + } +} + JSStringRef CYCopyJSString_(NSString *value) { #ifdef __APPLE__ - return JSStringCreateWithCFString(reinterpret_cast(string)); + return JSStringCreateWithCFString(reinterpret_cast(value)); #else - return CYCopyJSString([value UTF8String]); + CYPool pool; + return CYCopyJSString(CYPoolCString(pool, value)); #endif } @@ -223,10 +262,27 @@ CFStringRef CYCopyCFString(JSStringRef value) { return JSStringCopyCFString(kCFAllocatorDefault, value); } -CFStringRef CYCopyCFString(JSContextRef context, JSValueRef value) { - return CYCopyCFString(CYJSString(context, value)); +CFStringRef CYCopyCFString(const char *value) { + return CFStringCreateWithCString(kCFAllocatorDefault, value, kCFStringEncodingUTF8); +} + +template +NSString *CYCopyNSString(Type_ value) { + return (NSString *) CYCopyCFString(value); +} +#else +NSString *CYCopyNSString(const char *value) { + return [NSString stringWithUTF8String:value]; +} + +NSString *CYCopyNSString(JSStringRef value) { + return CYCopyNSString(CYCastCString_(value)); } #endif + +NSString *CYCopyNSString(JSContextRef context, JSValueRef value) { + return CYCopyNSString(CYJSString(context, value)); +} /* }}} */ static JSGlobalContextRef Context_; @@ -270,9 +326,12 @@ static JSObjectRef Array_pop_; static JSObjectRef Array_push_; static JSObjectRef Array_splice_; -static Class NSArray_; +#ifdef __APPLE__ static Class NSCFBoolean_; static Class NSCFType_; +#endif + +static Class NSArray_; static Class NSDictionary_; static Class NSMessageBuilder_; static Class NSZombie_; @@ -566,7 +625,7 @@ struct Type_privateData : static Type_privateData *Object; static Type_privateData *Selector; - static JSClassRef Class; + static JSClassRef Class_; ffi_type *ffi_; sig::Type *type_; @@ -622,6 +681,7 @@ struct Type_privateData : } }; +JSClassRef Type_privateData::Class_; Type_privateData *Type_privateData::Object; Type_privateData *Type_privateData::Selector; @@ -740,18 +800,6 @@ JSObjectRef CYMakeInstance(JSContextRef context, id object, bool transient) { return Instance::Make(context, object, flags); } -const char *CYPoolCString(apr_pool_t *pool, NSString *value) { - if (pool == NULL) - return [value UTF8String]; - else { - size_t size([value maximumLengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 1); - char *string(new(pool) char[size]); - if (![value getCString:string maxLength:size encoding:NSUTF8StringEncoding]) - @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"[NSString getCString:maxLength:encoding:] == NO" userInfo:nil]; - return string; - } -} - JSValueRef CYCastJSValue(JSContextRef context, bool value) { return JSValueMakeBoolean(context, value); } @@ -935,11 +983,31 @@ struct PropertyAttributes { #endif #ifdef __APPLE__ -NSString *NSCFType$cy$toJSON(id self, SEL sel, NSString *key) { +NSObject *NSCFType$cy$toJSON(id self, SEL sel, NSString *key) { return [(NSString *) CFCopyDescription((CFTypeRef) self) autorelease]; } #endif +#ifndef __APPLE__ +@interface CYWebUndefined : NSObject { +} + ++ (CYWebUndefined *) undefined; + +@end + +@implementation CYWebUndefined + ++ (CYWebUndefined *) undefined { + static CYWebUndefined *instance_([[CYWebUndefined alloc] init]); + return instance_; +} + +@end + +#define WebUndefined CYWebUndefined +#endif + /* Bridge: NSArray {{{ */ @implementation NSArray (Cycript) @@ -1117,8 +1185,12 @@ NSString *NSCFType$cy$toJSON(id self, SEL sel, NSString *key) { @implementation NSNumber (Cycript) - (JSType) cy$JSType { +#ifdef __APPLE__ // XXX: this just seems stupid - return [self class] == NSCFBoolean_ ? kJSTypeBoolean : kJSTypeNumber; + if ([self class] == NSCFBoolean_) + return kJSTypeBoolean; +#endif + return kJSTypeNumber; } - (NSObject *) cy$toJSON:(NSString *)key { @@ -1219,18 +1291,19 @@ NSString *NSCFType$cy$toJSON(id self, SEL sel, NSString *key) { - (NSString *) cy$toCYON { // XXX: this should use the better code from Output.cpp - CFMutableStringRef json(CFStringCreateMutableCopy(kCFAllocatorDefault, 0, (CFStringRef) self)); - CFStringFindAndReplace(json, CFSTR("\\"), CFSTR("\\\\"), CFRangeMake(0, CFStringGetLength(json)), 0); - CFStringFindAndReplace(json, CFSTR("\""), CFSTR("\\\""), CFRangeMake(0, CFStringGetLength(json)), 0); - CFStringFindAndReplace(json, CFSTR("\t"), CFSTR("\\t"), CFRangeMake(0, CFStringGetLength(json)), 0); - CFStringFindAndReplace(json, CFSTR("\r"), CFSTR("\\r"), CFRangeMake(0, CFStringGetLength(json)), 0); - CFStringFindAndReplace(json, CFSTR("\n"), CFSTR("\\n"), CFRangeMake(0, CFStringGetLength(json)), 0); + NSMutableString *json([self mutableCopy]); - CFStringInsert(json, 0, CFSTR("\"")); - CFStringAppend(json, CFSTR("\"")); + [json replaceOccurrencesOfString:@"\\" withString:@"\\\\" options:NSLiteralSearch range:NSMakeRange(0, [json length])]; + [json replaceOccurrencesOfString:@"\"" withString:@"\\\"" options:NSLiteralSearch range:NSMakeRange(0, [json length])]; + [json replaceOccurrencesOfString:@"\t" withString:@"\\t" options:NSLiteralSearch range:NSMakeRange(0, [json length])]; + [json replaceOccurrencesOfString:@"\r" withString:@"\\r" options:NSLiteralSearch range:NSMakeRange(0, [json length])]; + [json replaceOccurrencesOfString:@"\n" withString:@"\\n" options:NSLiteralSearch range:NSMakeRange(0, [json length])]; - return [reinterpret_cast(json) autorelease]; + [json appendString:@"\""]; + [json insertString:@"\"" atIndex:0]; + + return json; } - (NSString *) cy$toKey { @@ -1287,6 +1360,7 @@ NSString *NSCFType$cy$toJSON(id self, SEL sel, NSString *key) { @end /* }}} */ +/* Bridge: CYJSObject {{{ */ @interface CYJSObject : NSMutableDictionary { JSObjectRef object_; JSContextRef context_; @@ -1294,7 +1368,7 @@ NSString *NSCFType$cy$toJSON(id self, SEL sel, NSString *key) { - (id) initWithJSObject:(JSObjectRef)object inContext:(JSContextRef)context; -- (NSString *) cy$toJSON:(NSString *)key; +- (NSObject *) cy$toJSON:(NSString *)key; - (NSUInteger) count; - (id) objectForKey:(id)key; @@ -1303,7 +1377,8 @@ NSString *NSCFType$cy$toJSON(id self, SEL sel, NSString *key) { - (void) removeObjectForKey:(id)key; @end - +/* }}} */ +/* Bridge: CYJSArray {{{ */ @interface CYJSArray : NSMutableArray { JSObjectRef object_; JSContextRef context_; @@ -1321,6 +1396,7 @@ NSString *NSCFType$cy$toJSON(id self, SEL sel, NSString *key) { - (void) replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject; @end +/* }}} */ #define CYTry \ @try @@ -1336,7 +1412,7 @@ apr_status_t CYPoolRelease_(void *data) { return APR_SUCCESS; } -id CYPoolRelease(apr_pool_t *pool, id object) { +id CYPoolRelease_(apr_pool_t *pool, id object) { if (object == nil) return nil; else if (pool == NULL) @@ -1347,8 +1423,9 @@ id CYPoolRelease(apr_pool_t *pool, id object) { } } -CFTypeRef CYPoolRelease(apr_pool_t *pool, CFTypeRef object) { - return (CFTypeRef) CYPoolRelease(pool, (id) object); +template +Type_ CYPoolRelease(apr_pool_t *pool, Type_ object) { + return (Type_) CYPoolRelease_(pool, (id) object); } id CYCastNSObject_(apr_pool_t *pool, JSContextRef context, JSObjectRef object) { @@ -1387,29 +1464,21 @@ double CYCastDouble(JSContextRef context, JSValueRef value) { return number; } -CFNumberRef CYCopyCFNumber(JSContextRef context, JSValueRef value) { - double number(CYCastDouble(context, value)); - return CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &number); -} - -CFStringRef CYCopyCFString(const char *value) { - return CFStringCreateWithCString(kCFAllocatorDefault, value, kCFStringEncodingUTF8); -} - -NSString *CYCastNSString(apr_pool_t *pool, const char *value) { - return (NSString *) CYPoolRelease(pool, CYCopyCFString(value)); +NSNumber *CYCopyNSNumber(JSContextRef context, JSValueRef value) { + return [[NSNumber alloc] initWithDouble:CYCastDouble(context, value)]; } -NSString *CYCastNSString(apr_pool_t *pool, JSStringRef value) { - return (NSString *) CYPoolRelease(pool, CYCopyCFString(value)); +template +NSString *CYCastNSString(apr_pool_t *pool, Type_ value) { + return CYPoolRelease(pool, CYCopyNSString(value)); } bool CYCastBool(JSContextRef context, JSValueRef value) { return JSValueToBoolean(context, value); } -CFTypeRef CYCFType(apr_pool_t *pool, JSContextRef context, JSValueRef value, bool cast) { - CFTypeRef object; +id CYNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef value, bool cast) { + id object; bool copy; switch (JSType type = JSValueGetType(context, value)) { @@ -1423,23 +1492,28 @@ CFTypeRef CYCFType(apr_pool_t *pool, JSContextRef context, JSValueRef value, boo break; case kJSTypeBoolean: - object = CYCastBool(context, value) ? kCFBooleanTrue : kCFBooleanFalse; +#ifdef __APPLE__ + object = (id) (CYCastBool(context, value) ? kCFBooleanTrue : kCFBooleanFalse); copy = false; +#else + object = [[NSNumber alloc] initWithBoolean:value]; + copy = true; +#endif break; case kJSTypeNumber: - object = CYCopyCFNumber(context, value); + object = CYCopyNSNumber(context, value); copy = true; break; case kJSTypeString: - object = CYCopyCFString(context, value); + object = CYCopyNSString(context, value); copy = true; break; case kJSTypeObject: // XXX: this might could be more efficient - object = (CFTypeRef) CYCastNSObject(pool, context, (JSObjectRef) value); + object = CYCastNSObject(pool, context, (JSObjectRef) value); copy = false; break; @@ -1453,15 +1527,15 @@ CFTypeRef CYCFType(apr_pool_t *pool, JSContextRef context, JSValueRef value, boo else if (copy) return CYPoolRelease(pool, object); else - return CFRetain(object); + return [object retain]; } -CFTypeRef CYCastCFType(apr_pool_t *pool, JSContextRef context, JSValueRef value) { - return CYCFType(pool, context, value, true); +id CYCastNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef value) { + return CYNSObject(pool, context, value, true); } -CFTypeRef CYCopyCFType(apr_pool_t *pool, JSContextRef context, JSValueRef value) { - return CYCFType(pool, context, value, false); +id CYCopyNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef value) { + return CYNSObject(pool, context, value, false); } NSArray *CYCastNSArray(JSPropertyNameArrayRef names) { @@ -1473,10 +1547,6 @@ NSArray *CYCastNSArray(JSPropertyNameArrayRef names) { return array; } -id CYCastNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef value) { - return reinterpret_cast(CYCastCFType(pool, context, value)); -} - void CYThrow(JSContextRef context, JSValueRef value) { if (value == NULL) return; @@ -1826,21 +1896,6 @@ static bool CYGetOffset(apr_pool_t *pool, JSStringRef value, ssize_t &index) { return CYGetOffset(CYPoolCString(pool, value), index); } -// XXX: this macro is unhygenic -#define CYCastCString(context, value) ({ \ - char *utf8; \ - if (value == NULL) \ - utf8 = NULL; \ - else if (JSStringRef string = CYCopyJSString(context, value)) { \ - size_t size(JSStringGetMaximumUTF8CStringSize(string)); \ - utf8 = reinterpret_cast(alloca(size)); \ - JSStringGetUTF8CString(string, utf8, size); \ - JSStringRelease(string); \ - } else \ - utf8 = NULL; \ - utf8; \ -}) - static void *CYCastPointer_(JSContextRef context, JSValueRef value) { switch (JSValueGetType(context, value)) { case kJSTypeNull: @@ -2806,12 +2861,12 @@ static void ObjectiveC_Protocols_getPropertyNames(JSContextRef context, JSObject static JSObjectRef CYMakeType(JSContextRef context, const char *type) { Type_privateData *internal(new Type_privateData(NULL, type)); - return JSObjectMake(context, Type_, internal); + return JSObjectMake(context, Type_privateData::Class_, internal); } static JSObjectRef CYMakeType(JSContextRef context, sig::Type *type) { Type_privateData *internal(new Type_privateData(type)); - return JSObjectMake(context, Type_, internal); + return JSObjectMake(context, Type_privateData::Class_, internal); } static JSValueRef Runtime_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { @@ -3517,9 +3572,12 @@ MSInitialize { _pooled Bridge_ = [[NSMutableArray arrayWithContentsOfFile:@"/usr/lib/libcycript.plist"] retain]; - NSArray_ = objc_getClass("NSArray"); +#ifdef __APPLE__ NSCFBoolean_ = objc_getClass("NSCFBoolean"); NSCFType_ = objc_getClass("NSCFType"); +#endif + + NSArray_ = objc_getClass("NSArray"); NSDictionary_ = objc_getClass("NSDictonary"); NSMessageBuilder_ = objc_getClass("NSMessageBuilder"); NSZombie_ = objc_getClass("_NSZombie_"); @@ -3622,7 +3680,7 @@ JSGlobalContextRef CYGetJSContext() { definition.callAsFunction = &Type_callAsFunction; definition.callAsConstructor = &Type_callAsConstructor; definition.finalize = &Finalize; - Type_privateData::Class = JSClassCreate(&definition); + Type_privateData::Class_ = JSClassCreate(&definition); definition = kJSClassDefinitionEmpty; definition.className = "Runtime"; @@ -3705,7 +3763,7 @@ JSGlobalContextRef CYGetJSContext() { CYSetProperty(context, global, CYJSString("Instance"), Instance); CYSetProperty(context, global, CYJSString("Pointer"), JSObjectMakeConstructor(context, Pointer_, &Pointer_new)); CYSetProperty(context, global, CYJSString("Selector"), Selector); - CYSetProperty(context, global, CYJSString("Type"), JSObjectMakeConstructor(context, Type_, &Type_new)); + CYSetProperty(context, global, CYJSString("Type"), JSObjectMakeConstructor(context, Type_privateData::Class_, &Type_new)); MSHookFunction(&objc_registerClassPair, MSHake(objc_registerClassPair));