lib/utils/weak_class_dump/weak_classdump.cy
function commonTypes(type){
isPointer=NO;
if ([type containsSubstring:@"^"]){
isPointer=YES;
type=[type stringByReplacingOccurrencesOfString:@"^" withString:""];
}
switch (type.toString()){
case "d": type = "double"; break;
case "i": type = "int"; break;
case "f": type = "float"; break;
case "c": type = "BOOL"; break;
case "s": type = "short"; break;
case "I": type = "unsigned"; break;
case "l": type = "long"; break;
case "q": type = "long long"; break;
case "L": type = "unsigned long"; break;
case "C": type = "unsigned char"; break;
case "S": type = "unsigned short"; break;
case "Q": type = "unsigned long long"; break;
case "B": type = "_Bool"; break;
case "v": type = "void"; break;
case "*": type = "char*"; break;
case ":": type = "SEL"; break;
case "#": type = "Class"; break;
case "@": type = "id"; break;
case "@?": type = "id"; break;
case "Vv": type = "void"; break;
case "rv": type = "const void*"; break;
default: type = type;
}
return isPointer ? type.toString()+"*" : type.toString();
}
function getProtocolLines(protocol){
var protocolsMethodsString="";
currentProtocol=protocol;
protocolName=protocol_getName(currentProtocol);
protocolsMethodsString=protocolsMethodsString.toString()+"\n@protocol "+protocolName.toString()+"\n";
protPropertiesString="";
protPropertiesCount=new int;
protPropertyList=protocol_copyPropertyList(currentProtocol,protPropertiesCount);
for (xi=0; xi<*protPropertiesCount; xi++){
propname=property_getName(protPropertyList[xi]);
attrs=property_getAttributes(protPropertyList[xi]);
newString=propertyLineGenerator(attrs,propname).toString();
if (![protPropertiesString containsSubstring:newString]){
protPropertiesString=protPropertiesString.toString()+newString.toString();
}
}
protocolsMethodsString=protocolsMethodsString.toString()+protPropertiesString;
free(protPropertyList);
for (acase=0; acase<5; acase++){
protocolMethodsCount=new int;
isRequiredMethod=acase<2 ? NO : YES;
isInstanceMethod=(acase==0 || acase==2) ? NO : YES;
protMeths=protocol_copyMethodDescriptionList(currentProtocol, isRequiredMethod, isInstanceMethod, protocolMethodsCount);
for (gg=0; gg<*protocolMethodsCount; gg++){
if (acase<2 && ![[NSString stringWithString:protocolsMethodsString] containsSubstring:@"@optional"]){
protocolsMethodsString=protocolsMethodsString.toString()+"@optional\n";
}
if (acase>1 && ![[NSString stringWithString:protocolsMethodsString] containsSubstring:@"@required"]){
protocolsMethodsString=protocolsMethodsString.toString()+"@required\n";
}
startSign=isInstanceMethod==NO ? "+" : "-";
protSelector=protMeths[gg][0].toString();
protTypes=protMeths[gg][1];
protTypes=[protTypes stringByRemovingCharactersFromSet: [NSCharacterSet decimalDigitCharacterSet ]];
protTypes=[[NSString stringWithString:protTypes] stringByReplacingOccurrencesOfString:@"@:" withString:""];
returnType=[protTypes substringToIndex: 1];
returnType=commonTypes(returnType);
finString="";
if ([protTypes length]>1){
selectorsArray=[[NSString stringWithString:protSelector] componentsSeparatedByString:@":"];
typesArray=[NSMutableArray array];
for (typ=0; typ<[selectorsArray count]-1; typ++){
newobject=[NSString stringWithString:commonTypes([protTypes substringWithRange: [typ+1,1]])];
[typesArray addObject:newobject];
}
for (ad=0;ad<[typesArray count]; ad++){
argCount=ad+1;
finString=finString.toString()+selectorsArray[ad].toString()+"("+typesArray[ad].toString()+")"+":arg"+argCount.toString()+" ";
}
}
else{
finString=protSelector.toString();
}
finString=finString.toString()+";";
protocolsMethodsString=protocolsMethodsString.toString()+startSign.toString()+"("+returnType.toString()+")"+finString.toString()+"\n";
}
}
return protocolsMethodsString.toString()+"@end\n";
}
function constructTypeAndName(aType,IvarName,isIvar){
NSNotFound=2147483647;
compareString1=[NSString stringWithString:aType];
compareString2=[[[NSString stringWithString:aType] stringByReplacingOccurrencesOfString:"^" withString:""] stringByAppendingString:@"*"];
if (![[NSString stringWithString:commonTypes(aType)] isEqual:compareString1] && ![[NSString stringWithString:commonTypes(aType)] isEqual:compareString2]){
return commonTypes(aType).toString()+" "+IvarName.toString();
}
charSet=[NSCharacterSet characterSetWithCharactersInString:"@^\"{}="];
structCharSet=[NSCharacterSet characterSetWithCharactersInString:"?:{}="];
if ([aType rangeOfString:"]"].location!=NSNotFound && [aType rangeOfString:"^{"].location==NSNotFound){
aType=[aType stringByRemovingCharactersFromSet: [NSCharacterSet punctuationCharacterSet ]];
arrayCount=[[aType copy] stringByRemovingCharactersFromSet: [NSCharacterSet letterCharacterSet ]];
arrayType=[aType stringByRemovingCharactersFromSet: [NSCharacterSet decimalDigitCharacterSet ]];
return commonTypes(arrayType).toString()+"["+arrayCount.toString()+"]"+" "+IvarName.toString();
}
if ([aType rangeOfString:"{?"].length>0 && isIvar){
aType=[aType stringByRemovingCharactersFromSet:structCharSet];
structValues=[aType componentsSeparatedByString:@"\""];
structValues =[NSMutableArray arrayWithArray:structValues ];
firstEntry=[structValues removeObjectAtIndex:0];
[structValues removeObject:firstEntry];
newString=[NSString stringWithString:"struct {\n"];
namesArray=[NSMutableArray array];
typesArray=[NSMutableArray array];
for (d=0; d<[structValues count] ; d++){
if ((d % 2)==0){
[namesArray addObject:structValues[d]];
}
else{
[typesArray addObject:structValues[d]];
}
}
for (e=0; e<[typesArray count]; e++){
newString=newString.toString()+"\t\t"+constructTypeAndName(typesArray[e],namesArray[e],0).toString()+";\n";
}
return newString.toString()+"\t} "+IvarName.toString();
}
if ([aType rangeOfString:"{"].length>0){
returnValue="struct ";
range=[aType rangeOfString:@"="];
if ([aType containsSubstring:@"^{?="]){
aStruct=aType;
structString="";
someType="";
aStruct=[NSString stringWithString:aStruct];
aStruct=[aStruct stringByReplacingOccurrencesOfString:@"^{?=" withString:""];
aStruct=[aStruct stringByReplacingOccurrencesOfString:@"}" withString:""];
for (var f=0; f<[aStruct length]; f++){
currentLetter=[aStruct substringWithRange:[f,1]];
someType=constructTypeAndName(currentLetter,"",0);
someType=[someType stringByRemovingWhitespace];
structString=structString.toString()+"\t"+someType.toString()+" value"+(f+1).toString()+";\n";
}
structName="WCStruct_"+aStruct.toString();
if (![structsString containsSubstring:structName]){
structString="typedef struct{\n"+structString.toString();
structString=structString.toString()+"} "+structName.toString()+";\n\n";
structsString=structsString.toString()+structString.toString();
}
structName=structName.toString()+"*";
return structName+" "+IvarName.toString();
}
aType=[aType stringByReplacingCharactersInRange:[range.location,aType.length-range.location] withString:"" ];
returnValue=returnValue.toString()+[aType stringByRemovingCharactersFromSet:structCharSet].toString();
if ([returnValue containsSubstring:@"GSEvent"] || [returnValue containsSubstring:@"CTCall"]){
returnValue=[returnValue stringByReplacingOccurrencesOfString:"__" withString:""];
returnValue=[returnValue stringByReplacingOccurrencesOfString:"struct " withString:""];
returnValue=[returnValue stringByReplacingOccurrencesOfString:"^" withString:""];
returnValue=[returnValue stringByAppendingString:@"Ref"];
}
if ([returnValue containsSubstring:@"NSZone"]){
returnValue="NSZone*";
}
if ([returnValue containsSubstring:@"CGPoint"] || [returnValue containsSubstring:@"CGRect"] || [returnValue containsSubstring:@"CGSize"] ){
returnValue=[returnValue stringByReplacingOccurrencesOfString:@"struct " withString:@""];
}
return commonTypes(returnValue).toString()+" "+IvarName.toString();
}
if ([aType rangeOfString:@"^"].length>0){
range=[aType rangeOfString:"^" options: NULL range: [2,aType.length-2]];
if (range.length>0){
aType=[aType stringByReplacingCharactersInRange:[range.location-1,aType.length-range.location+1] withString:"" ];
}
aType=[aType stringByRemovingCharactersFromSet:charSet];
//aType=[aType stringByReplacingOccurrencesOfString:@"__" withString:""];
return aType.toString()+"* "+IvarName.toString();
}
if ([aType rangeOfString:@"@\""].length>0){
if ([aType rangeOfString:"<"].location==2){
aType="id"+aType.toString();
return [aType stringByRemovingCharactersFromSet:charSet].toString()+" "+IvarName.toString();
}
strippedString=[aType stringByRemovingCharactersFromSet:charSet];
return strippedString.toString()+ "* "+IvarName.toString();
}
if ([aType rangeOfString:@"b"].length>0 && [aType rangeOfString:":{"].length<1){
string=[aType stringByReplacingOccurrencesOfString:@"b" withString:""];
return "unsigned int "+IvarName.toString()+":"+string.toString();
}
return aType.toString() + " " + IvarName.toString();
}
function propertyLineGenerator(attributes,name){
parSet=[NSCharacterSet characterSetWithCharactersInString:@"()"];
attributes=[attributes stringByRemovingCharactersFromSet:parSet];
attrArr=[attributes componentsSeparatedByString:@","];
type=attrArr[0];
type=[type stringByReplacingCharactersInRange:[0,1] withString:""];
type=constructTypeAndName(type,"",0);
type=[type stringByRemovingWhitespace];
attrArr=[NSMutableArray arrayWithArray:attrArr];
[attrArr removeObjectAtIndex:0];
propertyString="@property ";
newPropsArray=[NSMutableArray array];
synthesize=[NSString stringWithString:""];
for each (attr in attrArr){
vToClear=nil;
if ([attr rangeOfString:@"V_"].location==0){
vToClear=attr;
attr=[attr stringByReplacingCharactersInRange:[0,2] withString:""];
synthesize="\t\t\t\t//@synthesize "+attr.toString()+"=_"+attr.toString()+" - In the implementation block";
}
if ([attr length]==1){
switch (attr.toString()){
case "R" : translatedProperty = "readonly";
case "C" : translatedProperty = "copy"; break;
case "&" : translatedProperty = "retain"; break;
case "N" : translatedProperty = "nonatomic"; break;
case "D" : translatedProperty = "@dynamic"; break;
case "W" : translatedProperty = "__weak"; break;
case "P" : translatedProperty = "t<encoding>"; break;
default: translatedProperty = attr;
}
[newPropsArray addObject:translatedProperty];
}
if ([attr rangeOfString:@"G"].location==0){
attr=[attr stringByReplacingCharactersInRange:[0,1] withString:""];
attr="getter="+attr.toString();
[newPropsArray addObject:attr];
}
if ([attr rangeOfString:@"S"].location==0){
attr=[attr stringByReplacingCharactersInRange:[0,1] withString:""];
attr="setter="+attr.toString();
[newPropsArray addObject:attr];
}
}
if ([newPropsArray containsObject:@"nonatomic"] && ![newPropsArray containsObject:@"assign"] && ![newPropsArray containsObject:@"readonly"] && ![newPropsArray containsObject:@"copy"] && ![newPropsArray containsObject:@"retain"]){
[newPropsArray addObject:@"assign"];
}
newPropsArray=[newPropsArray reversedArray];
rebuiltString=[newPropsArray componentsJoinedByString:","];
attrString=newPropsArray.length>0 ? "("+rebuiltString.toString()+")" : "(assign)";
propertyString=propertyString.toString()+attrString.toString()+" "+type.toString()+" "+name.toString()+"; "+synthesize.toString()+"\n";
return propertyString;
}
function methodLinesGenerator(methodList,methodsCount,isClassMethod){
methodLines="";
for (n=0; n<*methodsCount;n++){
method=methodList[n];
methodName=_method_getName(method);
returnType=_method_copyReturnType(method);
returnType=[constructTypeAndName([NSString stringWithString:returnType],[NSString stringWithString:""],0) stringByRemovingWhitespace];
argNum=_method_getNumberOfArguments(method);
methodBrokenDown=[methodName componentsSeparatedByString:@":"];
methodString=[NSString stringWithString:""];
if ([methodBrokenDown count]>1){
for (x=0; x<[methodBrokenDown count]-1; x++){
anIndex=x+2;
argumentType=_method_copyArgumentType(method,anIndex);
if (!argumentType){
argumentType="id";
}
typeName=constructTypeAndName([NSString stringWithString:argumentType],[NSString stringWithString:""],0);
typeName=[typeName stringByTrimmingLastCharacter];
methodString=methodString.toString()+methodBrokenDown[x].toString()+":("+typeName.toString()+")arg"+(x+1)+" ";
}
methodString=[methodString stringByTrimmingLastCharacter];
}
else{
methodString=methodName;
}
symbol=isClassMethod ? "+" : "-"; symbol=[NSString stringWithString:symbol];
newMethod=symbol.toString()+"("+returnType.toString()+")"+methodString.toString()+";\n";
cappedMethod=[methodName capitalizedString];
setterMethod="set"+cappedMethod.toString();
if (![methodsArray containsObject:newMethod] && ![propertiesString containsSubstring:methodName] && ![methodsString containsSubstring:setterMethod]){
[methodsArray addObject:newMethod];
methodLines=methodLines.toString()+newMethod.toString();
}
}
return methodLines;
}
function weak_classdump(classname,alsoDumpSuperclasses,outputdir){
//NSLog(@"weak_classdump: Dumping class %@",classname);
if (!classname){
return "Cannot find class";
}
if (typeof(alsoDumpSuperclasses) == 'undefined' || !alsoDumpSuperclasses){
alsoDumpSuperclasses=0;
}
structsString="";
interfaceString="";
version = [NSProcessInfo processInfo ].operatingSystemVersionString;
loc=[NSLocale localeWithLocaleIdentifier: "en-us"];
date=[NSDate.date descriptionWithLocale: loc];
classString = "/*\n * This header is generated by weak_classdump 0.2\n * on "+date.toString()+"\n * Operating System: "+version.toString()+"\n * weak_classdump is Freeware by Elias Limneos.\n *\n */\n\n";
if ( [[classname description] containsSubstring:@"<Protocol:"]){
classString=classString.toString()+getProtocolLines(classname).toString();
if (typeof(outputdir) == 'undefined'){
outputdir = "/tmp";
}
if (typeof(alsoDumpSuperclasses) == 'string'){
outputdir=alsoDumpSuperclasses;
}
outputdir=outputdir.toString()+"/";
if (![NSFileManager.defaultManager fileExistsAtPath:outputdir]){
try{
[NSFileManager.defaultManager createDirectoryAtPath:outputdir withIntermediateDirectories:YES attributes:nil error:nil];
}catch(e){}
}
classString = [NSString stringWithString:classString ];
if ([classString writeToFile:outputdir.toString()+classname.toString()+".h" atomically:YES]){
return "Wrote /PROTOCOL/ header file to "+outputdir.toString()+protocol_getName(classname).toString()+".h";
}
else {
NSSearchPathForDirectoriesInDomains=new Functor(dlsym(RTLD_DEFAULT,"NSSearchPathForDirectoriesInDomains"),"@ccc");
writeableDir=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
writeableDir=writeableDir[0];
return "Failed to write to "+outputdir.toString()+protocol_getName(classname).toString()+".h - Check file path and permissions? Suggested writeable directory: "+writeableDir.toString();
}
}
_class_copyIvarList = new Functor(dlsym(RTLD_DEFAULT,"class_copyIvarList"),"^^{objc_ivar=}#^I");
_class_copyProtocolList=new Functor(dlsym(RTLD_DEFAULT,"class_copyProtocolList"),"^@#^I");
_class_conformsToProtocol=new Functor(dlsym(RTLD_DEFAULT,"class_conformsToProtocol"),"B#@");
_class_copyMethodList=new Functor(dlsym(RTLD_DEFAULT,"class_copyMethodList"),"^^{objc_method=}#^I");
_class_copyPropertyList=new Functor(dlsym(RTLD_DEFAULT,"class_copyPropertyList"),"^^{objc_property=}#^I");
_method_getName=new Functor(dlsym(RTLD_DEFAULT,"method_getName"),"*^{objc_method=}");
_method_getNumberOfArguments=new Functor(dlsym(RTLD_DEFAULT,"method_getNumberOfArguments"),"I^{objc_method=}");
_method_copyReturnType=new Functor(dlsym(RTLD_DEFAULT,"method_copyReturnType"),"*^{objc_method=}");
_method_copyArgumentType=new Functor(dlsym(RTLD_DEFAULT,"method_copyArgumentType"),"*^{objc_method=}I");
_property_getAttributes=new Functor(dlsym(RTLD_DEFAULT,"property_getAttributes"),"*^{objc_property=}");
_property_getName=new Functor(dlsym(RTLD_DEFAULT,"property_getName"),"*^{objc_property=}");
_ivar_getName = new Functor(dlsym(RTLD_DEFAULT,"ivar_getName"),"*^?");
_ivar_getTypeEncoding = new Functor(dlsym(RTLD_DEFAULT,"ivar_getTypeEncoding"),"*^{objc_ivar=}");
_protocol_getName=new Functor(dlsym(RTLD_DEFAULT,"protocol_getName"),"*@");
_objc_getClassList=new Functor(dlsym(RTLD_DEFAULT,"objc_getClassList"),"i^#");
methodsArray=[NSMutableArray array];
propertiesString=@"";
methodsString=@"";
ivarsString=@"";
classMethodsString=@"";
startingClassname=classname;
superclass=classname.superclass;
protocolsCount=new int;
protocolArray=_class_copyProtocolList(classname,protocolsCount);
var protocolsMethodsString=classString;
var protocolName;
allProtocols="";
if (*protocolsCount>0){
for (iter=0; iter<*protocolsCount; iter++){
if (_class_conformsToProtocol(classname,protocolArray[iter])){
protocolName=protocol_getName(protocolArray[iter]);
protocolsMethodsString=protocolsMethodsString.toString()+getProtocolLines(protocolArray[iter]).toString();
}
protocolsMethodsString = [NSString stringWithString:protocolsMethodsString ];
classString=classString.toString()+"#import <"+protocolName.toString()+".h>\n";
if (typeof(outputdir)=="undefined" || outputdir==null){
outputdir="/tmp";
}
outputdir=outputdir+"/";
allProtocols=allProtocols.toString()+", "+outputdir.toString()+protocolName.toString()+".h";
if ([protocolsMethodsString writeToFile:outputdir.toString()+protocolName.toString()+".h" atomically:YES]){
//NSLog(@"Found Protocol %@, wrote to %@%@.h",protocolName,outputdir,protocolName);
}
}
}
protocolsString="";
if (*protocolsCount>0){
protocolsString=@" <".toString();
for (i=0; i<*protocolsCount; i++){
if (_class_conformsToProtocol(classname,protocolArray[i])){
comma=@"".toString();
if (i<*protocolsCount-1){
comma=@", ".toString();
}
protocolsString=protocolsString.toString()+_protocol_getName(protocolArray[i]).toString()+comma;
}
}
protocolsString=protocolsString+@">".toString();
}
if (classname.superclass!=nil && classname.superclass!="nil"){
interfaceString = [NSString stringWithString:@"\n@interface "+classname.toString()+" : "+classname.superclass.toString()].toString() + protocolsString.toString();
}
else{
interfaceString = [NSString stringWithString:@"\n@interface "+classname.toString()].toString() + protocolsString.toString();
}
while (classname!=NSObject && (classname.superclass!="nil" && classname.superclass!=NSObject) ) {
// Get Ivars
classIvarCount=new int;
superclassIvarCount=new int;
list=_class_copyIvarList(classname,classIvarCount);
superlist=_class_copyIvarList(superclass,superclassIvarCount);
superClassIvars=[NSMutableArray array];
for (i=0; i<*superclassIvarCount;i++){
if (_ivar_getName(superlist[i])){
[superClassIvars addObject:_ivar_getName(superlist[i])];
}
}
free(superlist);
for (i=0; i<*classIvarCount;i++){
classIvar=_ivar_getName(list[i]);
appendString="";
if (classIvar && ![superClassIvars containsObject:classIvar]){
ivarType=ivar_getTypeEncoding(list[i]).toString();
ivar=constructTypeAndName([NSString stringWithString:ivarType],[NSString stringWithString:_ivar_getName(list[i])],1);
newString="\n\t"+ivar.toString()+"; ";
if (![ivarsString containsSubstring:newString]){
ivarsString=ivarsString.toString()+newString.toString();
}
}
}
free(list);
// Get Properties
propertiesCount=new int;
propertyList=_class_copyPropertyList(classname,propertiesCount);
for (i=0; i<*propertiesCount; i++){
propname=_property_getName(propertyList[i]);
attrs=_property_getAttributes(propertyList[i]);
newString=propertyLineGenerator(attrs,propname).toString();
if (![propertiesString containsSubstring:newString]){
propertiesString=propertiesString.toString()+newString.toString();
}
}
free(propertyList);
// Get Methods
methodsCount=new int;
classMethodsCount=new int;
classMethodList=_class_copyMethodList(object_getClass(classname),classMethodsCount);
methodList=_class_copyMethodList(classname,methodsCount);
classMethodsString=classMethodsString.toString()+methodLinesGenerator(classMethodList,classMethodsCount,1).toString();
methodsString=methodsString.toString()+methodLinesGenerator(methodList,methodsCount,0).toString();
free(methodList);
free(classMethodList);
if (!alsoDumpSuperclasses)
break;
classname=classname.superclass ? classname.superclass : NSObject;
}
classString= classString.toString()+structsString.toString()+interfaceString.toString();
classString = classString.toString()+" {"+ivarsString.toString()+"\n}\n"+propertiesString.toString()+classMethodsString.toString()+methodsString.toString();
classString = classString.toString()+"@end";
if (typeof(outputdir) == 'undefined'){
outputdir = "/tmp";
}
if (typeof(alsoDumpSuperclasses) == 'string'){
outputdir=alsoDumpSuperclasses;
}
isDir= new boolean;
dirExists=[[NSFileManager defaultManager ] fileExistsAtPath:outputdir isDirectory: isDir] ;
if (!dirExists || !isDir){
createDirSucceeded = [[NSFileManager defaultManager ] createDirectoryAtPath:outputdir attributes: nil];
}
outputdir=outputdir.toString()+"/";
if (![NSFileManager.defaultManager fileExistsAtPath:outputdir]){
try{
[NSFileManager.defaultManager createDirectoryAtPath:outputdir withIntermediateDirectories:YES attributes:nil error:nil];
}catch(e){}
}
classString = [NSString stringWithString:classString ];
if ([classString writeToFile:outputdir.toString()+startingClassname.toString()+".h" atomically:YES]){
return "Wrote file to "+outputdir.toString()+startingClassname.toString()+".h"+allProtocols.toString();
}
else {
NSSearchPathForDirectoriesInDomains=new Functor(dlsym(RTLD_DEFAULT,"NSSearchPathForDirectoriesInDomains"),"@ccc");
writeableDir=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
writeableDir=writeableDir[0];
return "Failed to write to "+outputdir.toString()+startingClassname.toString()+".h - Check file path and permissions? Suggested writeable directory: "+writeableDir.toString();
}
}
function writeToSylogFromBgThread(string){
//NSLog(string);
}
function mweak_loadwdc_class(){
@implementation WCDBundleDumper : NSObject {}
+(id)dumpBundle:(id)infoDictionary{
var bundle=[infoDictionary objectForKey:@"bundle"];
var outputdir=[infoDictionary objectForKey:@"outputdir"];
writeToSylogFromBgThread(@"weak_classdump: Gathering all classes...please wait...");
var permittedNames = [ObjectiveC.classes allKeys].filter( function (name) { if ([name rangeOfString:"LA"].location!=0){ return [[NSBundle bundleForClass:objc_getClass(name.toString())] isEqual:bundle]; } else{ return NO; } } );
writeToSylogFromBgThread(@"weak_classdump: Found " + [permittedNames count].toString() +" classes matching your bundle. Starting dump...");
var results = [];
for (var i = 0; i < permittedNames.length; i++) {
try {
results.push(weak_classdump(objc_getClass(objc_getClass([[permittedNames[i] description] UTF8String])), false, outputdir));
} catch (e) {
}
}
[UIDevice.currentDevice _playSystemSound:1100]; // comment out to not produce any sound on finish
writeToSylogFromBgThread([NSString stringWithFormat:@"weak_classdump: Finished dumping bundle %@. Check output dir %@",bundle,outputdir]);
}
@end
}
function weak_classdump_bundle(bundle, outputdir) {
if (typeof(bundle)=="undefined"){
bundle=[NSBundle mainBundle];
}
if (![bundle isLoaded]){
//NSLog(@"weak_classdump: Bundle %@ is not loaded,attempting to load it",bundle);
[bundle load];
}
if (typeof(outputdir)=="undefined"){
outputdir="/tmp/";
}
var infoDict=[NSMutableDictionary dictionary];
[ infoDict setObject:bundle forKey:@"bundle"];
[ infoDict setObject:outputdir forKey:@"outputdir"];
try {
[WCDBundleDumper class];
} catch (e){
mweak_loadwdc_class();
}
[objc_getClass("WCDBundleDumper") performSelectorInBackground:@selector(dumpBundle:) withObject:infoDict ];
return "Dumping bundle... Check syslog. Will play lock sound when done."
}
if ( ! [NSString instancesRespondToSelector:@selector(stringByRemovingCharactersFromSet:)] ){
@implementation NSString (weakclassdump_compatibility)
- (void)removeCharactersInSet:(id)set{
length = [this length];
matchRange = [this rangeOfCharacterFromSet:set options:2 range:[0, length]];
while(matchRange.length > 0){
replaceRange = matchRange;
searchRange=[0,0];
searchRange.location = replaceRange.location + replaceRange.length;
searchRange.length = length - searchRange.location;
for(;;){
matchRange = [this rangeOfCharacterFromSet:set options:2 range:searchRange];
if((matchRange.length == 0) || (matchRange.location != searchRange.location))
break;
replaceRange.length += matchRange.length;
searchRange.length -= matchRange.length;
searchRange.location += matchRange.length;
}
[this deleteCharactersInRange:replaceRange];
matchRange.location -= replaceRange.length;
length -= replaceRange.length;
}
}
- (id)stringByRemovingCharactersFromSet:(id)set{
if([this rangeOfCharacterFromSet:set options:2].length == 0)
return this;
temp = [[this mutableCopyWithZone:[this zone]] autorelease];
[temp removeCharactersInSet:set];
temp=[temp stringByReplacingOccurrencesOfString: @"\"" withString: @""];
return temp;
}
@end
}
if ( ! [NSString instancesRespondToSelector:@selector(stringByRemovingWhitespace)] ){
@implementation NSString (weakclassdump_compatibility)
-(id)stringByRemovingWhitespace{
return [this stringByRemovingCharactersFromSet:[NSCharacterSet whitespaceCharacterSet]];
}
@end
}
//NSLog_ = dlsym(RTLD_DEFAULT, "NSLog")
//NSLog = function() { var types = 'v', args = [], count = arguments.length; for (var i = 0; i != count; ++i) { types += '@'; args.push(arguments[i]); } new Functor(NSLog_, types).apply(null, args); }
// Usage example : weak_classdump(SBAwayController);
// (will write to default path "/tmp/SBAwayController.h"
// example 2: weak_classdump(UIApplication,"/var/mobile/");
// will write to "/var/mobile/UIApplication.h"
// example 3: weak_classdump_bundle([NSBundle bundleWithPath:"/System/Library/Frameworks/iAd.framework"]);
// will dump all classes in the defined bundle to default dir "/tmp"
// example 4: weak_classdump_bundle([NSBundle bundleWithPath:"/System/Library/Frameworks/iAd.framework"],"/tmp/iAD.framework/Headers/");
// will dump all classes in the defined bundle to "/tmp/iAD.framework/"
"Added weak_classdump to \""+NSProcessInfo.processInfo .processName.toString()+"\" ("+NSProcessInfo.processInfo .processIdentifier.toString()+")";